wireshark/epan/dissectors/packet-btsdp.c
Michal Labedzki a99a0360c4 Bluetooth: Fix wrong recognized RFCOMM services
It seems that RFCOMM service can be dynamically changed while
connection is still alive. In other words: host can connect to
remote device and set one RFCOMM service (remote service), but later
remote device can change service to one of host service without
any disconnection. This patch add support for this case.
Also improve searching for useful UUID service through SDP.

Change-Id: I9e03b9b965d6b0d9761b4a451cdeb4a1a33ca017
Reviewed-on: https://code.wireshark.org/review/808
Reviewed-by: Anders Broman <a.broman58@gmail.com>
2014-03-25 09:13:13 +00:00

5702 lines
257 KiB
C

/* packet-btsdp.c
* Routines for Bluetooth SDP dissection
* Copyright 2002, Wolfgang Hansmann <hansmann@cs.uni-bonn.de>
* Copyright 2006, Ronnie Sahlberg
* - refactored for Wireshark checkin
* Copyright 2013, Michal Labedzki for Tieto Corporation
* - support SDP fragmentation (Continuation State)
* - implement DI 1.3
* - dissect profile specific attributes
* - fix service recognize
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/etypes.h>
#include <epan/ip_opts.h>
#include <epan/wmem/wmem.h>
#include <epan/strutil.h>
#include <epan/to_str.h>
#include "packet-bluetooth-hci.h"
#include "packet-btsdp.h"
#include "packet-btl2cap.h"
static gint proto_btsdp = -1;
static gint hf_pdu_id = -1;
static gint hf_tid = -1;
static gint hf_parameter_length = -1;
static gint hf_ssr_total_count = -1;
static gint hf_ssr_current_count = -1;
static gint hf_error_code = -1;
static gint hf_attribute_id_list = -1;
static gint hf_attribute_id_range = -1;
static gint hf_attribute_id_range_from = -1;
static gint hf_attribute_id_range_to = -1;
static gint hf_attribute_list_byte_count = -1;
static gint hf_maximum_service_record_count = -1;
static gint hf_maximum_attribute_byte_count = -1;
static gint hf_continuation_state = -1;
static gint hf_continuation_state_length = -1;
static gint hf_continuation_state_value = -1;
static gint hf_fragment = -1;
static gint hf_partial_record_handle_list = -1;
static gint hf_reassembled_record_handle_list = -1;
static gint hf_partial_attribute_list = -1;
static gint hf_reassembled_attribute_list = -1;
static gint hf_data_element = -1;
static gint hf_data_element_size = -1;
static gint hf_data_element_type = -1;
static gint hf_data_element_var_size = -1;
static gint hf_data_element_value = -1;
static gint hf_data_element_value_nil = -1;
static gint hf_data_element_value_boolean = -1;
static gint hf_data_element_value_signed_int = -1;
static gint hf_data_element_value_unsigned_int = -1;
static gint hf_data_element_value_uuid_16 = -1;
static gint hf_data_element_value_uuid_32 = -1;
static gint hf_data_element_value_uuid_128 = -1;
static gint hf_data_element_value_uuid = -1;
static gint hf_data_element_value_string = -1;
static gint hf_data_element_value_url = -1;
static gint hf_data_element_value_alternative = -1;
static gint hf_data_element_value_sequence = -1;
static gint hf_profile_descriptor_list = -1;
static gint hf_attribute_list = -1;
static gint hf_attribute_lists = -1;
static gint hf_service_search_pattern = -1;
static gint hf_service_record_handle_list = -1;
static gint hf_service_attribute = -1;
static gint hf_service_attribute_id = -1;
static gint hf_service_attribute_value = -1;
static gint hf_service_attribute_id_generic = -1;
static gint hf_service_attribute_id_a2dp = -1;
static gint hf_service_attribute_id_avrcp = -1;
static gint hf_service_attribute_id_ctp = -1;
static gint hf_service_attribute_id_bip_imaging_responder = -1;
static gint hf_service_attribute_id_bip_imaging_other = -1;
static gint hf_service_attribute_id_bpp = -1;
static gint hf_service_attribute_id_bpp_rui = -1;
static gint hf_service_attribute_id_did = -1;
static gint hf_service_attribute_id_dun = -1;
static gint hf_service_attribute_id_fax = -1;
static gint hf_service_attribute_id_ftp = -1;
static gint hf_service_attribute_id_gnss = -1;
static gint hf_service_attribute_id_hfp_hf = -1;
static gint hf_service_attribute_id_hfp_ag = -1;
static gint hf_service_attribute_id_hcrp = -1;
static gint hf_service_attribute_id_hsp = -1;
static gint hf_service_attribute_id_hdp = -1;
static gint hf_service_attribute_id_hid = -1;
static gint hf_service_attribute_id_wap = -1;
static gint hf_service_attribute_id_map_mas = -1;
static gint hf_service_attribute_id_opp = -1;
static gint hf_service_attribute_id_pan_nap = -1;
static gint hf_service_attribute_id_pan_gn = -1;
static gint hf_service_attribute_id_pan_panu = -1;
static gint hf_service_attribute_id_pbap = -1;
static gint hf_service_attribute_id_synch = -1;
static gint hf_did_specification_id = -1;
static gint hf_did_vendor_id = -1;
static gint hf_did_vendor_id_bluetooth_sig = -1;
static gint hf_did_vendor_id_usb_forum = -1;
static gint hf_did_product_id = -1;
static gint hf_did_primary_record = -1;
static gint hf_did_version = -1;
static gint hf_did_vendor_id_source = -1;
static gint hf_a2dp_sink_supported_features_reserved = -1;
static gint hf_a2dp_sink_supported_features_amplifier = -1;
static gint hf_a2dp_sink_supported_features_recorder = -1;
static gint hf_a2dp_sink_supported_features_speaker = -1;
static gint hf_a2dp_sink_supported_features_headphone = -1;
static gint hf_a2dp_source_supported_features_reserved = -1;
static gint hf_a2dp_source_supported_features_mixer = -1;
static gint hf_a2dp_source_supported_features_tuner = -1;
static gint hf_a2dp_source_supported_features_microphone = -1;
static gint hf_a2dp_source_supported_features_player = -1;
static gint hf_synch_supported_data_store = -1;
static gint hf_ctp_external_network = -1;
static gint hf_avrcp_ct_supported_features_reserved_7_15 = -1;
static gint hf_avrcp_ct_supported_features_browsing = -1;
static gint hf_avrcp_ct_supported_features_reserved_4_5 = -1;
static gint hf_avrcp_ct_supported_features_category_4 = -1;
static gint hf_avrcp_ct_supported_features_category_3 = -1;
static gint hf_avrcp_ct_supported_features_category_2 = -1;
static gint hf_avrcp_ct_supported_features_category_1 = -1;
static gint hf_avrcp_tg_supported_features_reserved_8_15 = -1;
static gint hf_avrcp_tg_supported_features_multiple_player = -1;
static gint hf_avrcp_tg_supported_features_browsing = -1;
static gint hf_avrcp_tg_supported_features_group_navigation = -1;
static gint hf_avrcp_tg_supported_features_settings = -1;
static gint hf_avrcp_tg_supported_features_category_4 = -1;
static gint hf_avrcp_tg_supported_features_category_3 = -1;
static gint hf_avrcp_tg_supported_features_category_2 = -1;
static gint hf_avrcp_tg_supported_features_category_1 = -1;
static gint hf_hsp_remote_audio_volume_control = -1;
static gint hf_gnss_supported_features = -1;
static gint hf_pbap_pse_supported_repositories_reserved = -1;
static gint hf_pbap_pse_supported_repositories_sim_card = -1;
static gint hf_pbap_pse_supported_repositories_local_phonebook = -1;
static gint hf_fax_support_class_1 = -1;
static gint hf_fax_support_class_2 = -1;
static gint hf_fax_support_class_2_vendor = -1;
static gint hf_fax_support_audio_feedback = -1;
static gint hf_ftp_goep_l2cap_psm = -1;
static gint hf_map_mas_instance_id = -1;
static gint hf_map_mas_supported_message_types_reserved = -1;
static gint hf_map_mas_supported_message_types_mms = -1;
static gint hf_map_mas_supported_message_types_sms_cdma = -1;
static gint hf_map_mas_supported_message_types_sms_gsm = -1;
static gint hf_map_mas_supported_message_types_email = -1;
static gint hf_hcrp_1284_id = -1;
static gint hf_hcrp_device_location = -1;
static gint hf_hcrp_device_name = -1;
static gint hf_hcrp_friendly_name = -1;
static gint hf_wap_network_address = -1;
static gint hf_wap_gateway = -1;
static gint hf_wap_homepage_url = -1;
static gint hf_wap_stack_type = -1;
static gint hf_hdp_data_exchange = -1;
static gint hf_hdp_support_procedure_reserved_5_7 = -1;
static gint hf_hdp_support_procedure_sync_master_role = -1;
static gint hf_hdp_support_procedure_clock_synchronization_protocol = -1;
static gint hf_hdp_support_procedure_reconnect_acceptance = -1;
static gint hf_hdp_support_procedure_reconnect_initiation = -1;
static gint hf_hdp_support_procedure_reserved = -1;
static gint hf_hdp_supported_features_data = -1;
static gint hf_hdp_supported_features_data_mdep_id = -1;
static gint hf_hdp_supported_features_data_mdep_data_type = -1;
static gint hf_hdp_supported_features_data_mdep_role = -1;
static gint hf_hdp_supported_features_data_mdep_description = -1;
static gint hf_hdp_supported_features_mdep_id = -1;
static gint hf_hdp_supported_features_mdep_data_type = -1;
static gint hf_hdp_supported_features_mdep_role = -1;
static gint hf_hdp_supported_features_mdep_description = -1;
static gint hf_pan_sercurity_description = -1;
static gint hf_pan_ipv4_subnet = -1;
static gint hf_pan_ipv6_subnet = -1;
static gint hf_pan_max_net_access_rate = -1;
static gint hf_pan_net_access_type = -1;
static gint hf_opp_goep_l2cap_psm = -1;
static gint hf_opp_supported_format = -1;
static gint hf_dun_escape_sequence = -1;
static gint hf_dun_support_audio_feedback = -1;
static gint hf_hfp_hf_supported_features_reserved = -1;
static gint hf_hfp_hf_supported_features_wide_band_speech = -1;
static gint hf_hfp_hf_supported_features_remote_volume_control = -1;
static gint hf_hfp_hf_supported_features_voice_recognition_activation = -1;
static gint hf_hfp_hf_supported_features_cli_presentation_capability = -1;
static gint hf_hfp_hf_supported_features_call_waiting_or_three_way_calling = -1;
static gint hf_hfp_hf_supported_features_ec_and_or_nr_function = -1;
static gint hf_hfp_gw_network = -1;
static gint hf_hfp_gw_supported_features_reserved = -1;
static gint hf_hfp_gw_supported_features_wide_band_speech = -1;
static gint hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag = -1;
static gint hf_hfp_gw_supported_features_inband_ring_tone_capability = -1;
static gint hf_hfp_gw_supported_features_voice_recognition_function = -1;
static gint hf_hfp_gw_supported_features_ec_and_or_nr_function = -1;
static gint hf_hfp_gw_supported_features_three_way_calling = -1;
static gint hf_sdp_protocol_item = -1;
static gint hf_sdp_protocol = -1;
static gint hf_sdp_protocol_psm = -1;
static gint hf_sdp_protocol_channel = -1;
static gint hf_sdp_protocol_gatt_handle_start = -1;
static gint hf_sdp_protocol_gatt_handle_end = -1;
static gint hf_sdp_protocol_version = -1;
static gint hf_sdp_protocol_bnep_type = -1;
static gint hf_sdp_service_record_handle = -1;
static gint hf_sdp_service_record_state = -1;
static gint hf_sdp_service_info_time_to_live = -1;
static gint hf_sdp_service_availability = -1;
static gint hf_sdp_service_documentation_url = -1;
static gint hf_sdp_service_client_executable_url = -1;
static gint hf_sdp_service_icon_url = -1;
static gint hf_sdp_service_name = -1;
static gint hf_sdp_service_description = -1;
static gint hf_sdp_service_provider_name = -1;
static gint hf_sdp_lang = -1;
static gint hf_sdp_lang_id = -1;
static gint hf_sdp_lang_code = -1;
static gint hf_sdp_lang_encoding = -1;
static gint hf_sdp_lang_attribute_base = -1;
static gint hf_hid_descriptor_list_descriptor_data = -1;
static gint hf_hid_lang = -1;
static gint hf_hid_device_release_number = -1;
static gint hf_hid_parser_version = -1;
static gint hf_hid_device_subclass_type = -1;
static gint hf_hid_device_subclass_subtype = -1;
static gint hf_hid_device_subclass_reserved = -1;
static gint hf_hid_country_code = -1;
static gint hf_hid_virtual_cable = -1;
static gint hf_hid_reconnect_initiate = -1;
static gint hf_hid_sdp_disable = -1;
static gint hf_hid_battery_power = -1;
static gint hf_hid_remote_wake = -1;
static gint hf_hid_profile_version = -1;
static gint hf_hid_supervision_timeout = -1;
static gint hf_hid_normally_connectable = -1;
static gint hf_hid_boot_device = -1;
static gint hf_hid_ssr_host_max_latency = -1;
static gint hf_hid_ssr_host_min_timeout = -1;
static gint hf_hid_descriptor_list_type = -1;
static gint hf_hid_descriptor_list_descriptor = -1;
static gint hf_bip_goep_l2cap_psm = -1;
static gint hf_bip_supported_capabilities_reserved_4_7 = -1;
static gint hf_bip_supported_capabilities_displaying = -1;
static gint hf_bip_supported_capabilities_printing = -1;
static gint hf_bip_supported_capabilities_capturing = -1;
static gint hf_bip_supported_capabilities_genering_imaging = -1;
static gint hf_bip_supported_features_reserved_9_15 = -1;
static gint hf_bip_supported_features_remote_display = -1;
static gint hf_bip_supported_features_remote_camera = -1;
static gint hf_bip_supported_features_automatic_archive = -1;
static gint hf_bip_supported_features_advanced_image_printing = -1;
static gint hf_bip_supported_features_image_pull = -1;
static gint hf_bip_supported_features_image_push_display = -1;
static gint hf_bip_supported_features_image_push_print = -1;
static gint hf_bip_supported_features_image_push_store = -1;
static gint hf_bip_supported_features_image_push = -1;
static gint hf_bip_supported_functions_reserved_17_31 = -1;
static gint hf_bip_supported_functions_get_status = -1;
static gint hf_bip_supported_functions_reserved_15 = -1;
static gint hf_bip_supported_functions_get_monitoring_image = -1;
static gint hf_bip_supported_functions_start_archive = -1;
static gint hf_bip_supported_functions_reserved_12 = -1;
static gint hf_bip_supported_functions_start_print = -1;
static gint hf_bip_supported_functions_delete_image = -1;
static gint hf_bip_supported_functions_get_linked_attachment = -1;
static gint hf_bip_supported_functions_get_linked_thumbnail = -1;
static gint hf_bip_supported_functions_get_image = -1;
static gint hf_bip_supported_functions_get_image_property = -1;
static gint hf_bip_supported_functions_get_images_list = -1;
static gint hf_bip_supported_functions_remote_display = -1;
static gint hf_bip_supported_functions_put_linked_thumbnail = -1;
static gint hf_bip_supported_functions_put_linked_attachment = -1;
static gint hf_bip_supported_functions_put_image = -1;
static gint hf_bip_supported_functions_get_capabilities = -1;
static gint hf_bip_supported_functions_reserved_13_31 = -1;
static gint hf_bip_supported_functions_get_partial_image = -1;
static gint hf_bip_supported_functions_reserved_1_11 = -1;
static gint hf_bip_supported_functions_reserved_1_4 = -1;
static gint hf_bip_supported_functions_reserved_11_31 = -1;
static gint hf_bip_total_imaging_data_capacity = -1;
static gint hf_bpp_document_formats_supported = -1;
static gint hf_bpp_character_repertoires_support = -1;
static gint hf_bpp_xhtml_print_image_formats_supported = -1;
static gint hf_bpp_color_supported = -1;
static gint hf_bpp_1284_id = -1;
static gint hf_bpp_printer_name = -1;
static gint hf_bpp_printer_location = -1;
static gint hf_bpp_duplex_supported = -1;
static gint hf_bpp_media_types_supported = -1;
static gint hf_bpp_max_media_width = -1;
static gint hf_bpp_max_media_length = -1;
static gint hf_bpp_enhanced_layout_supported = -1;
static gint hf_bpp_rui_formats_supported = -1;
static gint hf_bpp_reference_printing_rui_supported = -1;
static gint hf_bpp_direct_printing_rui_supported = -1;
static gint hf_bpp_reference_printing_top_url = -1;
static gint hf_bpp_direct_printing_top_url = -1;
static gint hf_bpp_device_name = -1;
static gint hf_bpp_printer_admin_rui_top_url = -1;
static gint ett_btsdp = -1;
static gint ett_btsdp_ssr = -1;
static gint ett_btsdp_des = -1;
static gint ett_btsdp_attribute = -1;
static gint ett_btsdp_attribute_id = -1;
static gint ett_btsdp_attribute_value = -1;
static gint ett_btsdp_attribute_idlist = -1;
static gint ett_btsdp_service_search_pattern = -1;
static gint ett_btsdp_continuation_state = -1;
static gint ett_btsdp_data_element = -1;
static gint ett_btsdp_data_element_value = -1;
static gint ett_btsdp_reassembled = -1;
static gint ett_btsdp_supported_features = -1;
static gint ett_btsdp_supported_features_mdep_id = -1;
static gint ett_btsdp_supported_features_mdep_data_type = -1;
static gint ett_btsdp_supported_features_mdep_role = -1;
static gint ett_btsdp_supported_features_mdep_description = -1;
static gint ett_btsdp_protocol = -1;
static expert_field ei_btsdp_continuation_state_none = EI_INIT;
static expert_field ei_btsdp_continuation_state_large = EI_INIT;
static expert_field ei_data_element_value_large = EI_INIT;
static dissector_handle_t btsdp_handle;
static dissector_table_t btrfcomm_service_table;
static dissector_table_t btl2cap_service_table;
static wmem_tree_t *tid_requests = NULL;
static wmem_tree_t *continuation_states = NULL;
static wmem_tree_t *record_handle_services = NULL;
static wmem_tree_t *service_infos = NULL;
typedef struct _tid_request_t {
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 tid;
guint32 pdu_type;
wmem_array_t *uuid_array;
guint32 record_handle;
guint8 *continuation_state;
guint8 continuation_state_length;
guint32 data_length;
guint8 *data;
} tid_request_t;
typedef struct _continuation_state_data_t {
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 pdu_type;
guint32 continuation_state[5];
guint32 data_length;
guint8 *data;
} continuation_state_data_t;
typedef struct _record_handle_service_t {
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 record_handle;
wmem_array_t *uuid_array;
} record_handle_service_t;
#define PDU_TYPE_SERVICE_SEARCH 0x00
#define PDU_TYPE_SERVICE_ATTRIBUTE 0x01
#define PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE 0x02
#define MAX_SDP_LEN 1024
extern value_string_ext ext_usb_vendors_vals;
extern value_string_ext ext_usb_products_vals;
static const value_string vs_pduid[] = {
{ 0x01, "Error Response" },
{ 0x02, "Service Search Request" },
{ 0x03, "Service Search Response" },
{ 0x04, "Service Attribute Request" },
{ 0x05, "Service Attribute Response" },
{ 0x06, "Service Search Attribute Request" },
{ 0x07, "Service Search Attribute Response" },
{ 0, NULL }
};
static const value_string vs_general_attribute_id[] = {
{ 0x0000, "Service Record Handle" },
{ 0x0001, "Service Class ID List" },
{ 0x0002, "Service Record State" },
{ 0x0003, "Service ID" },
{ 0x0004, "Protocol Descriptor List" },
{ 0x0005, "Browse Group List" },
{ 0x0006, "Language Base Attribute ID List" },
{ 0x0007, "Service Info Time To Live" },
{ 0x0008, "Service Availability" },
{ 0x0009, "Bluetooth Profile Descriptor List" },
{ 0x000A, "Documentation URL" },
{ 0x000B, "Client Executable URL" },
{ 0x000C, "Icon URL" },
{ 0x000D, "Additional Protocol Descriptor Lists" },
/* Localized string default offset is 0x100,
the rest based on Language Base Attribute ID List */
{ 0x0100, "Service Name" },
{ 0x0101, "Service Description" },
{ 0x0102, "Provider Name" },
{ 0, NULL }
};
static const value_string vs_a2dp_attribute_id[] = {
{ 0x0311, "Supported Features" },
{ 0, NULL }
};
static const value_string vs_avrcp_attribute_id[] = {
{ 0x0311, "Supported Features" },
{ 0, NULL }
};
static const value_string vs_bip_imaging_responder_attribute_id[] = {
{ 0x0200, "GOEP L2CAP PSM" },
{ 0x0310, "Supported Capabilities" },
{ 0x0311, "Supported Features" },
{ 0x0312, "Supported Functions" },
{ 0x0313, "Total Imaging Data Capacity" },
{ 0, NULL }
};
static const value_string vs_bip_imaging_other_attribute_id[] = {
{ 0x0200, "GOEP L2CAP PSM" },
{ 0x0312, "Supported Functions" },
{ 0, NULL }
};
static const value_string vs_bpp_attribute_id[] = {
{ 0x0350, "Document Formats Supported" },
{ 0x0352, "Character Repertoires Supported" },
{ 0x0354, "XHTML-Print Image Formats Supported" },
{ 0x0356, "Color Supported" },
{ 0x0358, "1284ID" },
{ 0x035A, "Printer Name" },
{ 0x035C, "Printer Location" },
{ 0x035E, "Duplex Supported" },
{ 0x0360, "Media Types Supported" },
{ 0x0362, "Max Media Width" },
{ 0x0364, "Max Media Length" },
{ 0x0366, "Enhanced Layout Supported" },
{ 0x0368, "RUI Formats Supported" },
{ 0x0370, "Reference Printing RUI Supported" },
{ 0x0372, "Direct Printing RUI Supported" },
{ 0x0374, "Reference Printing Top URL" },
{ 0x0376, "Direct Printing Top URL" },
{ 0x037A, "Device Name" },
{ 0, NULL }
};
static const value_string vs_bpp_reflected_ui_attribute_id[] = {
{ 0x0368, "RUI Formats Supported" },
{ 0x0378, "Printer Admin RUI Top URL" },
{ 0, NULL }
};
static const value_string vs_ctp_attribute_id[] = {
{ 0x0301, "External Network" },
{ 0, NULL }
};
static const value_string vs_did_attribute_id[] = {
{ 0x0200, "Specification ID" },
{ 0x0201, "Vendor ID" },
{ 0x0202, "Product ID" },
{ 0x0203, "Version" },
{ 0x0204, "Primary Record" },
{ 0x0205, "Vendor ID Source" },
{ 0, NULL }
};
static const value_string vs_dun_attribute_id[] = {
{ 0x0305, "Audio Feedback Support" },
{ 0x0306, "Escape Sequence" },
{ 0, NULL }
};
static const value_string vs_fax_attribute_id[] = {
{ 0x0302, "Fax Class 1 Support" },
{ 0x0303, "Fax Class 2.0 Support" },
{ 0x0304, "Fax Class 2 Support (vendor-specific class)" },
{ 0x0305, "Audio Feedback Support" },
{ 0, NULL }
};
static const value_string vs_ftp_attribute_id[] = {
{ 0x0200, "GOEP L2CAP PSM" },
{ 0, NULL }
};
static const value_string vs_gnss_attribute_id[] = {
{ 0x0200, "Supported Features" },
{ 0, NULL }
};
static const value_string vs_hfp_gw_attribute_id[] = {
{ 0x0311, "Supported Features" },
{ 0, NULL }
};
static const value_string vs_hfp_ag_attribute_id[] = {
{ 0x0301, "Network" },
{ 0x0311, "Supported Features" },
{ 0, NULL }
};
static const value_string vs_hcrp_attribute_id[] = {
{ 0x0300, "1284ID" },
{ 0x0302, "Device Name" },
{ 0x0304, "Friendly Name" },
{ 0x0306, "Device Location" },
{ 0, NULL }
};
static const value_string vs_hsp_attribute_id[] = {
{ 0x0302, "Remote Audio Volume Control" },
{ 0, NULL }
};
static const value_string vs_hdp_attribute_id[] = {
{ 0x0200, "Support Features List" },
{ 0x0301, "Data Exchange Specification" },
{ 0x0302, "MCAP Supported Procedures" },
{ 0, NULL }
};
static const value_string vs_hid_attribute_id[] = {
{ 0x0200, "Device Release Number" },
{ 0x0201, "Parser Version" },
{ 0x0202, "Device Subclass" },
{ 0x0203, "Country Code" },
{ 0x0204, "Virtual Cable" },
{ 0x0205, "Reconnect Initiate" },
{ 0x0206, "Descriptor List" },
{ 0x0207, "LANG ID Base List" },
{ 0x0208, "SDP Disable" },
{ 0x0209, "Battery Power" },
{ 0x020A, "Remote Wake" },
{ 0x020B, "Profile Version" },
{ 0x020C, "Supervision Timeout" },
{ 0x020D, "Normally Connectable" },
{ 0x020E, "BootDevice" },
{ 0x020F, "SSR Host Max Latency" },
{ 0x0210, "SSR Host Min Timeout" },
{ 0, NULL }
};
static const value_string vs_wap_attribute_id[] = {
{ 0x0306, "Network Address" },
{ 0x0307, "WAP Gateway" },
{ 0x0308, "Home Page URL" },
{ 0x0309, "WAP Stack Type" },
{ 0, NULL }
};
static const value_string vs_map_mas_attribute_id[] = {
{ 0x0315, "MAS Instance ID" },
{ 0x0316, "Supported Message Types" },
{ 0, NULL }
};
static const value_string vs_opp_attribute_id[] = {
{ 0x0200, "GOEP L2CAP PSM" },
{ 0x0300, "Service Version" },
{ 0x0303, "Supported Formats List" },
{ 0, NULL }
};
static const value_string vs_pan_nap_attribute_id[] = {
{ 0x0200, "IP Subnet" }, /* Deprecated */
{ 0x030A, "Security Description" },
{ 0x030B, "Net Access Type" },
{ 0x030C, "Max Net Access Rate" },
{ 0x030D, "IPv4Subnet" },
{ 0x030E, "IPv6Subnet" },
{ 0, NULL }
};
static const value_string vs_pan_gn_attribute_id[] = {
{ 0x0200, "IP Subnet" }, /* Deprecated */
{ 0x030A, "Security Description" },
{ 0x030D, "IPv4Subnet" },
{ 0x030E, "IPv6Subnet" },
{ 0, NULL }
};
static const value_string vs_pan_panu_attribute_id[] = {
{ 0x030A, "Security Description" },
{ 0, NULL }
};
static const value_string vs_pbap_attribute_id[] = {
{ 0x0314, "Supported Repositories" },
{ 0, NULL }
};
static const value_string vs_synch_attribute_id[] = {
{ 0x0301, "Supported Data Stores List" },
{ 0, NULL }
};
static const value_string did_vendor_id_source_vals[] = {
{ 0x0001, "Bluetooth SIG" },
{ 0x0002, "USB Implementer's Forum" },
{ 0, NULL }
};
value_string_ext did_vendor_id_source_vals_ext = VALUE_STRING_EXT_INIT(did_vendor_id_source_vals);
static const value_string synch_supported_data_store_vals[] = {
{ 0x01, "Phonebook" },
{ 0x03, "Calendar" },
{ 0x05, "Notes" },
{ 0x06, "Messages" },
{ 0, NULL }
};
static const value_string ctp_external_network_vals[] = {
{ 0x01, "Phonebook" },
{ 0x02, "ISDN" },
{ 0x03, "GSM" },
{ 0x04, "CDMA" },
{ 0x05, "Analogue Cellular" },
{ 0x06, "Packet-switched" },
{ 0x07, "Other" },
{ 0, NULL }
};
static const value_string wap_stack_type_vals[] = {
{ 0x01, "Connectionless" },
{ 0x02, "Connection Oriented" },
{ 0x03, "All (Connectionless + Connection Oriented)" },
{ 0, NULL }
};
static const value_string wap_gateway_vals[] = {
{ 0x01, "Origin Server" },
{ 0x02, "Proxy" },
{ 0, NULL }
};
static const value_string hdp_data_exchange_specification_vals[] = {
{ 0x01, "ISO/IEEE 11073-20601 (Health informatics)" },
{ 0, NULL }
};
static const range_string hdp_mdep_id_rvals[] = {
{ 0x00, 0x00, "Reserved For Echo Test Function" },
{ 0x01, 0x7F, "Available for use" },
{ 0x80, 0xFF, "Reserved by MCAP" },
{ 0, 0, NULL }
};
static const value_string hdp_mdep_role_vals[] = {
{ 0x00, "Source" },
{ 0x01, "Sink" },
{ 0, NULL }
};
static const value_string pan_security_description_vals[] = {
{ 0x0000, "None" },
{ 0x0001, "Service-level Enforced Security" },
{ 0x0002, "802.1x Security" },
{ 0, NULL }
};
static const value_string opp_supported_format_vals[] = {
{ 0x01, "vCard 2.1" },
{ 0x02, "vCard 3.0" },
{ 0x03, "vCal 1.0" },
{ 0x04, "iCal 2.0" },
{ 0x05, "vNote" },
{ 0x06, "vMessage" },
{ 0xFF, "AllFormats" },
{ 0, NULL }
};
static const value_string pan_net_access_type_vals[] = {
{ 0x0000, "PSTN" },
{ 0x0001, "ISDN" },
{ 0x0002, "DSL" },
{ 0x0003, "Cable Modem" },
{ 0x0004, "10Mb Ethernet" },
{ 0x0005, "100Mb Ethernet" },
{ 0x0006, "4Mb Token Ring" },
{ 0x0007, "16Mb Token Ring" },
{ 0x0008, "100Mb Token Ring" },
{ 0x0009, "FDDI" },
{ 0x000A, "GSM" },
{ 0x000B, "CDMA" },
{ 0x000c, "GPRS" },
{ 0x000D, "3G" },
{ 0xFFFE, "Other" },
{ 0, NULL }
};
static const value_string hfp_gw_network_vals[] = {
{ 0x00, "No ability to reject a call" },
{ 0x01, "Ability to reject a call" },
{ 0, NULL }
};
static const value_string hid_device_subclass_type_vals[] = {
{ 0x00, "Not Keyboard / Not Pointing Device" },
{ 0x01, "Keyboard" },
{ 0x02, "Pointing Device" },
{ 0x03, "Combo keyboard/pointing device" },
{ 0, NULL }
};
static const value_string hid_device_subclass_subtype_vals[] = {
{ 0x00, "Uncategorized device" },
{ 0x01, "Joystick" },
{ 0x02, "Gamepad" },
{ 0x03, "Remote control" },
{ 0x04, "Sensing device" },
{ 0x05, "Digitizer tablet" },
{ 0x06, "Card Reader" },
{ 0, NULL }
};
/* USB HID 1.11 bCountryCode */
static const value_string hid_country_code_vals[] = {
{ 0, "Not Supported" },
{ 1, "Arabic" },
{ 2, "Belgian" },
{ 3, "Canadian-Bilingual" },
{ 4, "Canadian-French" },
{ 5, "Czech Republic" },
{ 6, "Danish" },
{ 7, "Finnish" },
{ 8, "French" },
{ 9, "German" },
{ 10, "Greek" },
{ 11, "Hebrew" },
{ 12, "Hungary" },
{ 13, "International (ISO)" },
{ 14, "Italian" },
{ 15, "Japan (Katakana)" },
{ 16, "Korean" },
{ 17, "Latin American" },
{ 18, "Netherlands/Dutch" },
{ 19, "Norwegian" },
{ 20, "Persian (Farsi)" },
{ 21, "Poland" },
{ 22, "Portuguese" },
{ 23, "Russia" },
{ 24, "Slovakia" },
{ 25, "Spanish" },
{ 26, "Swedish" },
{ 27, "Swiss/French" },
{ 28, "Swiss/German" },
{ 29, "Switzerland" },
{ 30, "Taiwan" },
{ 31, "Turkish-Q" },
{ 32, "UK" },
{ 33, "US" },
{ 34, "Yugoslavia" },
{ 35, "Turkish-F" },
{ 0, NULL }
};
static const value_string descriptor_list_type_vals[] = {
{ 0x22, "Report" },
{ 0x23, "Physical"},
{ 0, NULL }
};
static const value_string vs_error_code[] = {
{ 0x0001, "Invalid/Unsupported SDP Version" },
{ 0x0002, "Invalid Service Record Handle" },
{ 0x0003, "Invalid Request Syntax" },
{ 0x0004, "Invalid PDU Size" },
{ 0x0005, "Invalid Continuation State" },
{ 0x0006, "Insufficient Resources to Satisfy Request" },
{ 0, NULL }
};
static const value_string vs_data_element_size[] = {
{ 0x00, "1 byte (0 bytes if Nil)" },
{ 0x01, "2 bytes" },
{ 0x02, "4 bytes" },
{ 0x03, "8 bytes" },
{ 0x04, "16 bytes" },
{ 0x05, "uint8" },
{ 0x06, "uint16" },
{ 0x07, "uint32" },
{ 0, NULL }
};
static const value_string vs_data_element_type[] = {
{ 0x00, "Nil" },
{ 0x01, "Unsigned Integer" },
{ 0x02, "Signed Twos-Complement Integer" },
{ 0x03, "UUID" },
{ 0x04, "Text string" },
{ 0x05, "Boolean" },
{ 0x06, "Sequence" },
{ 0x07, "Alternative" },
{ 0x08, "URL" },
{ 0, NULL }
};
const custom_uuid_t custom_uuid[] = {
{ {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Server" },
{ {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02}, 16, "SyncML Client" },
{ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, NULL},
};
extern value_string_ext ext_psm_vals;
extern value_string_ext wap_mib_enum_vals_character_sets_ext;
extern value_string_ext usb_langid_vals_ext;
void proto_register_btsdp(void);
void proto_reg_handoff_btsdp(void);
service_info_t* btsdp_get_service_info(wmem_tree_key_t* key)
{
if (service_infos == NULL)
return NULL;
return (service_info_t *)wmem_tree_lookup32_array_le(service_infos, key);
}
static uuid_t
get_specified_uuid(wmem_array_t *uuid_array)
{
uuid_t uuid;
/* Try to find UUID that is already use in RFCOMM or L2CAP, otherwise try to
return last one (most generic).
NOTE: UUIDs in array are from (most specified) to (most generic) */
if (uuid_array) {
guint32 i_uuid;
guint32 size;
uuid_t *p_uuid = NULL;
size = wmem_array_get_count(uuid_array);
for (i_uuid = 0; i_uuid < size; i_uuid += 1) {
p_uuid = (uuid_t *) wmem_array_index(uuid_array, i_uuid);
if (dissector_get_uint_handle(btrfcomm_service_table, p_uuid->bt_uuid))
break;
if (dissector_get_uint_handle(btl2cap_service_table, p_uuid->bt_uuid))
break;
}
if (p_uuid) return *p_uuid;
}
memset(&uuid, 0, sizeof(uuid_t));
return uuid;
}
static gchar *
print_uuid(uuid_t *uuid)
{
if (uuid->bt_uuid) {
return wmem_strdup(wmem_packet_scope(), val_to_str_ext_const(uuid->bt_uuid, &bt_sig_uuid_vals_ext, "Unknown"));
} else {
guint i_uuid;
i_uuid = 0;
while (custom_uuid[i_uuid].name) {
if (custom_uuid[i_uuid].size != uuid->size) {
i_uuid += 1;
continue;
}
if (memcmp(uuid->data, custom_uuid[i_uuid].uuid, uuid->size) == 0) {
return wmem_strdup(wmem_packet_scope(), custom_uuid[i_uuid].name);
}
i_uuid += 1;
}
return bytes_to_ep_str(uuid->data, uuid->size);
}
}
static wmem_array_t *
get_uuids(packet_info *pinfo, guint32 record_handle, btl2cap_data_t *l2cap_data)
{
record_handle_service_t *record_handle_service;
wmem_tree_key_t key[7];
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_chandle;
guint32 k_psm;
guint32 k_record_handle;
guint32 k_frame_number;
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 frame_number;
interface_id = l2cap_data->interface_id;
adapter_id = l2cap_data->adapter_id;
chandle = l2cap_data->chandle;
psm = l2cap_data->psm;
frame_number = pinfo->fd->num;
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_record_handle = record_handle;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_record_handle;
key[5].length = 1;
key[5].key = &k_frame_number;
key[6].length = 0;
key[6].key = NULL;
record_handle_service = (record_handle_service_t *) wmem_tree_lookup32_array_le(record_handle_services, key);
if (record_handle_service && record_handle_service->interface_id == interface_id &&
record_handle_service->adapter_id == adapter_id &&
record_handle_service->chandle == chandle &&
record_handle_service->psm == psm &&
record_handle_service->record_handle == record_handle) {
return record_handle_service->uuid_array;
}
return NULL;
}
static service_info_t *
save_channel(packet_info *pinfo, guint32 type_protocol, guint32 channel,
gint protocol_order, service_info_t *parent_service_info)
{
wmem_tree_key_t key[10];
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_sdp_psm;
guint32 k_direction;
guint32 k_bd_addr_oui;
guint32 k_bd_addr_id;
guint32 k_service_type;
guint32 k_service_channel;
guint32 k_frame_number;
service_info_t *service_info;
service_info = (service_info_t *) wmem_new(wmem_file_scope(), service_info_t);
service_info->interface_id = parent_service_info->interface_id;
service_info->adapter_id = parent_service_info->adapter_id;
service_info->sdp_psm = parent_service_info->sdp_psm;
service_info->direction = parent_service_info->direction;
service_info->bd_addr_oui = parent_service_info->bd_addr_oui;
service_info->bd_addr_id = parent_service_info->bd_addr_id;
service_info->type = type_protocol;
service_info->channel = channel;
service_info->uuid = parent_service_info->uuid;
service_info->protocol = -1;
service_info->protocol_order = protocol_order;
service_info->parent_info = parent_service_info;
service_info->data = parent_service_info->data;
k_interface_id = service_info->interface_id;
k_adapter_id = service_info->adapter_id;
k_sdp_psm = service_info->sdp_psm;
k_direction = service_info->direction;
k_bd_addr_oui = service_info->bd_addr_oui;
k_bd_addr_id = service_info->bd_addr_id;
k_service_type = service_info->type;
k_service_channel = service_info->channel;
k_frame_number = pinfo->fd->num;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_sdp_psm;
key[3].length = 1;
key[3].key = &k_direction;
key[4].length = 1;
key[4].key = &k_bd_addr_oui;
key[5].length = 1;
key[5].key = &k_bd_addr_id;
key[6].length = 1;
key[6].key = &k_service_type;
key[7].length = 1;
key[7].key = &k_service_channel;
key[8].length = 1;
key[8].key = &k_frame_number;
key[9].length = 0;
key[9].key = NULL;
wmem_tree_insert32_array(service_infos, key, service_info);
return service_info;
}
static gint
get_type_length(tvbuff_t *tvb, gint offset, gint *length)
{
gint size = 0;
guint8 byte;
byte = tvb_get_guint8(tvb, offset);
offset += 1;
switch (byte & 0x07) {
case 0:
size = (byte >> 3) == 0 ? 0 : 1;
break;
case 1:
size = 2;
break;
case 2:
size = 4;
break;
case 3:
size = 8;
break;
case 4:
size = 16;
break;
case 5:
size = tvb_get_guint8(tvb, offset);
offset += 1;
break;
case 6:
size = tvb_get_ntohs(tvb, offset);
offset += 2;
break;
case 7:
size = tvb_get_ntohl(tvb, offset);
offset += 4;
break;
}
if (size < 0) {
*length = 0; /* Add expert info? */
}
else {
*length = size;
}
return offset;
}
static guint32
get_uint_by_size(tvbuff_t *tvb, gint off, gint size)
{
switch (size) {
case 0:
return tvb_get_guint8(tvb, off);
case 1:
return tvb_get_ntohs(tvb, off);
case 2:
return tvb_get_ntohl(tvb, off);
default:
return 0xffffffff;
}
}
static gint32
get_int_by_size(tvbuff_t *tvb, gint off, gint size)
{
switch (size) {
case 0:
return tvb_get_guint8(tvb, off);
case 1:
return tvb_get_ntohs(tvb, off);
case 2:
return tvb_get_ntohl(tvb, off);
default:
return -1;
}
}
static gint
dissect_uuid(proto_tree *tree, tvbuff_t *tvb, gint offset, gint size, uuid_t *uuid)
{
proto_item *item;
DISSECTOR_ASSERT(uuid);
if (size == 2) {
proto_tree_add_item(tree, hf_data_element_value_uuid_16, tvb, offset, size, ENC_BIG_ENDIAN);
uuid->bt_uuid = tvb_get_ntohs(tvb, offset);
} else if (size == 4 && tvb_get_ntohs(tvb, offset) == 0x0000) {
proto_tree_add_item(tree, hf_data_element_value_uuid_32, tvb, offset, size, ENC_BIG_ENDIAN);
uuid->bt_uuid = tvb_get_ntohs(tvb, offset + 2);
} else if (size == 16 && tvb_get_ntohs(tvb, offset) == 0x0000 && tvb_get_ntohl(tvb, offset + 4) == 0x1000 && tvb_get_ntoh64(tvb, offset + 8) == G_GUINT64_CONSTANT(0x800000805F9B34FB)) {
item = proto_tree_add_item(tree, hf_data_element_value_uuid_128, tvb, offset, size, ENC_NA);
uuid->bt_uuid = tvb_get_ntohs(tvb, offset + 2);
proto_item_append_text(item, " (%s)", val_to_str_ext_const(uuid->bt_uuid, &bt_sig_uuid_vals_ext, "Unknown"));
} else {
guint i_uuid;
item = proto_tree_add_item(tree, hf_data_element_value_uuid, tvb, offset, size, ENC_NA);
i_uuid = 0;
while (custom_uuid[i_uuid].name) {
if (custom_uuid[i_uuid].size != size) {
i_uuid += 1;
continue;
}
if (tvb_memeql(tvb, offset, custom_uuid[i_uuid].uuid, 4) == 0) {
proto_item_append_text(item, " (%s)", custom_uuid[i_uuid].name);
break;
}
i_uuid += 1;
}
uuid->bt_uuid = 0;
}
if (size == 2 || size == 4 || size == 16) {
uuid->size = size;
tvb_memcpy(tvb, uuid->data, offset, size);
} else {
uuid->size = 0;
}
return offset + size;
}
static gint
dissect_continuation_state(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
gint offset)
{
proto_item *cont_item;
guint length;
length = tvb_length_remaining(tvb, offset);
if (length == 0) {
proto_tree_add_expert(tree, pinfo, &ei_btsdp_continuation_state_none, tvb, offset, -1);
} else if (length > 17) {
proto_tree_add_expert(tree, pinfo, &ei_btsdp_continuation_state_large, tvb, offset, -1);
} else if (length == 1 && tvb_get_guint8(tvb, offset) == 0x00) {
proto_tree_add_none_format(tree, hf_continuation_state, tvb,
offset, -1, "Continuation State: no (00)");
} else {
proto_item *cont_tree;
guint data;
guint8 i_data;
guint8 continuation_state_length;
continuation_state_length = tvb_get_guint8(tvb, offset);
cont_item = proto_tree_add_none_format(tree, hf_continuation_state, tvb, offset,
1 + continuation_state_length, "Continuation State: yes (");
cont_tree = proto_item_add_subtree(cont_item, ett_btsdp_continuation_state);
proto_tree_add_item(cont_tree, hf_continuation_state_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(cont_tree, hf_continuation_state_value, tvb, offset,
continuation_state_length, ENC_NA);
for (i_data = 0; i_data < continuation_state_length - 1; ++i_data) {
data = tvb_get_guint8(tvb, offset);
proto_item_append_text(cont_item, "%02X ", data);
offset += 1;
}
data = tvb_get_guint8(tvb, offset);
proto_item_append_text(cont_item, "%02X)", data);
offset += 1;
}
return offset;
}
static gint
reassemble_continuation_state(tvbuff_t *tvb, packet_info *pinfo,
gint offset, guint tid, gboolean is_request,
gint attribute_list_byte_offset, gint attribute_list_byte_count,
guint32 pdu_type, tvbuff_t **new_tvb, gboolean *is_first,
gboolean *is_continued, wmem_array_t **uuid_array,
guint32 *record_handle, btl2cap_data_t *l2cap_data)
{
guint length;
tid_request_t *tid_request;
continuation_state_data_t *continuation_state_data;
wmem_tree_key_t key[12];
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_chandle;
guint32 k_psm;
guint32 k_tid;
guint32 k_pdu_type;
guint32 k_frame_number;
guint8 *k_continuation_state;
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 frame_number;
guint32 *continuation_state_array;
if (new_tvb) *new_tvb = NULL;
interface_id = l2cap_data->interface_id;
adapter_id = l2cap_data->adapter_id;
chandle = l2cap_data->chandle;
psm = l2cap_data->psm;
frame_number = pinfo->fd->num;
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_tid = tid;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_tid;
key[5].length = 1;
key[5].key = &k_frame_number;
key[6].length = 0;
key[6].key = NULL;
if (is_first) *is_first = TRUE;
if (is_continued) *is_continued = TRUE;
length = tvb_length_remaining(tvb, offset);
if (length == 0) {
return offset;
} else if (length > 17) {
return offset;
} else if (length == 1 && tvb_get_guint8(tvb, offset) == 0x00) {
if (is_continued) *is_continued = FALSE;
if (!pinfo->fd->flags.visited) {
if (is_request) {
tid_request = (tid_request_t *) wmem_new(wmem_file_scope(), tid_request_t);
tid_request->interface_id = interface_id;
tid_request->adapter_id = adapter_id;
tid_request->chandle = chandle;
tid_request->psm = psm;
tid_request->tid = tid;
if (uuid_array)
tid_request->uuid_array = *uuid_array;
else
tid_request->uuid_array = NULL;
if (record_handle)
tid_request->record_handle = *record_handle;
else
tid_request->record_handle = 0;
tid_request->data = NULL;
tid_request->data_length = 0;
tid_request->pdu_type = pdu_type;
tid_request->continuation_state = NULL;
tid_request->continuation_state_length = 0;
wmem_tree_insert32_array(tid_requests, key, tid_request);
} else {
tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
if (tid_request && tid_request->interface_id == interface_id &&
tid_request->adapter_id == adapter_id &&
tid_request->chandle == chandle &&
tid_request->psm == psm &&
tid_request->tid == tid) {
if (tid_request->continuation_state_length > 0) {
/* fetch tid_request->continuation_state */
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = tid_request->continuation_state_length;
memcpy(&k_continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);
continuation_state_array = (guint32 *) k_continuation_state;
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = tid_request->continuation_state_length;
memcpy(&k_continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_pdu_type = tid_request->pdu_type;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_pdu_type;
key[5].length = 1;
key[5].key = (guint32 *) &k_continuation_state[0];
key[6].length = 1;
key[6].key = (guint32 *) &k_continuation_state[4];
key[7].length = 1;
key[7].key = (guint32 *) &k_continuation_state[8];
key[8].length = 1;
key[8].key = (guint32 *) &k_continuation_state[12];
key[9].length = 1;
key[9].key = (guint32 *) &k_continuation_state[16];
key[10].length = 1;
key[10].key = &k_frame_number;
key[11].length = 0;
key[11].key = NULL;
continuation_state_data = (continuation_state_data_t *) wmem_tree_lookup32_array_le(continuation_states, key);
if (continuation_state_data && continuation_state_data->interface_id == interface_id &&
continuation_state_data->adapter_id == adapter_id &&
continuation_state_data->chandle == chandle &&
continuation_state_data->psm == psm &&
continuation_state_data->pdu_type == tid_request->pdu_type &&
continuation_state_data->continuation_state[0] == continuation_state_array[0] &&
continuation_state_data->continuation_state[1] == continuation_state_array[1] &&
continuation_state_data->continuation_state[2] == continuation_state_array[2] &&
continuation_state_data->continuation_state[3] == continuation_state_array[3] &&
continuation_state_data->continuation_state[4] == continuation_state_array[4]) {
tid_request->data = (guint8 *) wmem_alloc(wmem_file_scope(), continuation_state_data->data_length + attribute_list_byte_count);
tid_request->data_length = continuation_state_data->data_length + attribute_list_byte_count;
memcpy(tid_request->data, continuation_state_data->data, continuation_state_data->data_length);
tvb_memcpy(tvb, tid_request->data + continuation_state_data->data_length, attribute_list_byte_offset, attribute_list_byte_count);
}
} else {
tid_request->data = (guint8 *) wmem_alloc(wmem_file_scope(), attribute_list_byte_count);
tid_request->data_length = attribute_list_byte_count;
tvb_memcpy(tvb, tid_request->data, attribute_list_byte_offset, attribute_list_byte_count);
}
if (uuid_array) *uuid_array = tid_request->uuid_array;
if (record_handle) *record_handle = tid_request->record_handle;
}
}
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_tid = tid;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_tid;
key[5].length = 1;
key[5].key = &k_frame_number;
key[6].length = 0;
key[6].key = NULL;
}
/* full reassemble */
if (!is_request) {
tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
if (tid_request && tid_request->interface_id == interface_id &&
tid_request->adapter_id == adapter_id &&
tid_request->chandle == chandle &&
tid_request->psm == psm &&
tid_request->tid == tid) {
tvbuff_t *next_tvb;
next_tvb = tvb_new_child_real_data(tvb, tid_request->data,
tid_request->data_length, tid_request->data_length);
if (new_tvb) *new_tvb = next_tvb;
if (tid_request->continuation_state_length) *is_first = FALSE;
if (uuid_array) *uuid_array = tid_request->uuid_array;
if (record_handle) *record_handle = tid_request->record_handle;
}
}
} else {
guint8 *continuation_state;
guint8 continuation_state_length;
guint8 *packet_scope_string;
continuation_state_length = tvb_get_guint8(tvb, offset);
offset++;
continuation_state = (guint8 *) wmem_alloc(wmem_file_scope(), continuation_state_length);
packet_scope_string = tvb_bytes_to_ep_str(tvb, offset, continuation_state_length);
memcpy(continuation_state, packet_scope_string, continuation_state_length);
if (!pinfo->fd->flags.visited) {
if (is_request) {
tid_request = (tid_request_t *) wmem_new(wmem_file_scope(), tid_request_t);
tid_request->interface_id = interface_id;
tid_request->adapter_id = adapter_id;
tid_request->chandle = chandle;
tid_request->psm = psm;
tid_request->tid = tid;
if (uuid_array)
tid_request->uuid_array = *uuid_array;
else
tid_request->uuid_array = NULL;
if (record_handle)
tid_request->record_handle = *record_handle;
else
tid_request->record_handle = 0;
/* fetch data saved in continuation_state */
tid_request->data = NULL;
tid_request->data_length = 0;
tid_request->pdu_type = pdu_type;
tid_request->continuation_state = continuation_state;
tid_request->continuation_state_length = continuation_state_length;
wmem_tree_insert32_array(tid_requests, key, tid_request);
} else {
tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
if (tid_request && tid_request->interface_id == interface_id &&
tid_request->adapter_id == adapter_id &&
tid_request->chandle == chandle &&
tid_request->psm == psm &&
tid_request->tid == tid) {
/* data comes from here and saved in previous continuation_state */
if (tid_request->continuation_state_length > 0) {
/* fetch tid_request->continuation_state */
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = tid_request->continuation_state_length;
memcpy(&k_continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);
continuation_state_array = (guint32 *) k_continuation_state;
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = tid_request->continuation_state_length;
memcpy(&k_continuation_state[1], tid_request->continuation_state, tid_request->continuation_state_length);
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_pdu_type = tid_request->pdu_type;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_pdu_type;
key[5].length = 1;
key[5].key = (guint32 *) &k_continuation_state[0];
key[6].length = 1;
key[6].key = (guint32 *) &k_continuation_state[4];
key[7].length = 1;
key[7].key = (guint32 *) &k_continuation_state[8];
key[8].length = 1;
key[8].key = (guint32 *) &k_continuation_state[12];
key[9].length = 1;
key[9].key = (guint32 *) &k_continuation_state[16];
key[10].length = 1;
key[10].key = &k_frame_number;
key[11].length = 0;
key[11].key = NULL;
continuation_state_data = (continuation_state_data_t *) wmem_tree_lookup32_array_le(continuation_states, key);
if (continuation_state_data && continuation_state_data->interface_id == interface_id &&
continuation_state_data->adapter_id == adapter_id &&
continuation_state_data->chandle == chandle &&
continuation_state_data->psm == psm &&
continuation_state_data->pdu_type == tid_request->pdu_type &&
continuation_state_data->continuation_state[0] == continuation_state_array[0] &&
continuation_state_data->continuation_state[1] == continuation_state_array[1] &&
continuation_state_data->continuation_state[2] == continuation_state_array[2] &&
continuation_state_data->continuation_state[3] == continuation_state_array[3] &&
continuation_state_data->continuation_state[4] == continuation_state_array[4]) {
tid_request->data = (guint8 *) wmem_alloc(wmem_file_scope(), continuation_state_data->data_length + attribute_list_byte_count);
tid_request->data_length = continuation_state_data->data_length + attribute_list_byte_count;
memcpy(tid_request->data, continuation_state_data->data, continuation_state_data->data_length);
tvb_memcpy(tvb, tid_request->data + continuation_state_data->data_length, attribute_list_byte_offset, attribute_list_byte_count);
}
} else {
tid_request->data = (guint8 *) wmem_alloc(wmem_file_scope(), attribute_list_byte_count);
tid_request->data_length = attribute_list_byte_count;
tvb_memcpy(tvb, tid_request->data, attribute_list_byte_offset, attribute_list_byte_count);
}
if (uuid_array) *uuid_array = tid_request->uuid_array;
if (record_handle) *record_handle = tid_request->record_handle;
/* save tid_request in continuation_state data */
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = continuation_state_length;
memcpy(&k_continuation_state[1], continuation_state, continuation_state_length);
continuation_state_array = (guint32 *) k_continuation_state;
k_continuation_state = (guint8 *) wmem_alloc0(wmem_packet_scope(), 20);
k_continuation_state[0] = continuation_state_length;
memcpy(&k_continuation_state[1], continuation_state, continuation_state_length);
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_pdu_type = pdu_type;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_pdu_type;
key[5].length = 1;
key[5].key = (guint32 *) &k_continuation_state[0];
key[6].length = 1;
key[6].key = (guint32 *) &k_continuation_state[4];
key[7].length = 1;
key[7].key = (guint32 *) &k_continuation_state[8];
key[8].length = 1;
key[8].key = (guint32 *) &k_continuation_state[12];
key[9].length = 1;
key[9].key = (guint32 *) &k_continuation_state[16];
key[10].length = 1;
key[10].key = &k_frame_number;
key[11].length = 0;
key[11].key = NULL;
continuation_state_data = (continuation_state_data_t *) wmem_new(wmem_file_scope(), continuation_state_data_t);
continuation_state_data->interface_id = interface_id;
continuation_state_data->adapter_id = adapter_id;
continuation_state_data->chandle = chandle;
continuation_state_data->psm = psm;
continuation_state_data->pdu_type = pdu_type;
continuation_state_data->continuation_state[0] = continuation_state_array[0];
continuation_state_data->continuation_state[1] = continuation_state_array[1];
continuation_state_data->continuation_state[2] = continuation_state_array[2];
continuation_state_data->continuation_state[3] = continuation_state_array[3];
continuation_state_data->continuation_state[4] = continuation_state_array[4];
continuation_state_data->data = tid_request->data;
continuation_state_data->data_length = tid_request->data_length;
wmem_tree_insert32_array(continuation_states, key, continuation_state_data);
}
}
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_tid = tid;
k_frame_number = frame_number;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_tid;
key[5].length = 1;
key[5].key = &k_frame_number;
key[6].length = 0;
key[6].key = NULL;
}
/* partial reassemble */
if (!is_request) {
tid_request = (tid_request_t *) wmem_tree_lookup32_array_le(tid_requests, key);
if (tid_request && tid_request->interface_id == interface_id &&
tid_request->adapter_id == adapter_id &&
tid_request->chandle == chandle &&
tid_request->psm == psm &&
tid_request->tid == tid) {
tvbuff_t *next_tvb;
next_tvb = tvb_new_child_real_data(tvb, tid_request->data,
tid_request->data_length, tid_request->data_length);
if (new_tvb) *new_tvb = next_tvb;
if (tid_request->continuation_state_length) *is_first = FALSE;
if (uuid_array) *uuid_array = tid_request->uuid_array;
if (record_handle) *record_handle = tid_request->record_handle;
}
}
}
return offset;
}
static gint
dissect_data_element(proto_tree *tree, proto_tree **next_tree,
packet_info *pinfo, tvbuff_t *tvb, gint offset)
{
proto_item *pitem;
proto_tree *ptree;
gint new_offset;
gint length;
gint len;
guint8 type;
guint8 size;
new_offset = get_type_length(tvb, offset, &length) - 1;
type = tvb_get_guint8(tvb, offset);
size = type & 0x07;
type = type >> 3;
pitem = proto_tree_add_none_format(tree, hf_data_element, tvb, offset, 0, "Data Element: %s %s",
val_to_str_const(type, vs_data_element_type, "Unknown Type"),
val_to_str_const(size, vs_data_element_size, "Unknown Size"));
ptree = proto_item_add_subtree(pitem, ett_btsdp_data_element);
len = (new_offset - offset) + length;
proto_item_set_len(pitem, len + 1);
proto_tree_add_item(ptree, hf_data_element_type, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(ptree, hf_data_element_size, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
if (new_offset > offset - 1) {
proto_tree_add_uint(ptree, hf_data_element_var_size, tvb,
offset, len - length, length);
proto_item_append_text(pitem, (length != 1) ? " %u bytes" : " %u byte", length);
offset += len - length;
}
pitem = proto_tree_add_item(ptree, hf_data_element_value, tvb, offset, 0, ENC_NA);
if (length > tvb_length_remaining(tvb, offset)) {
expert_add_info(pinfo, pitem, &ei_data_element_value_large);
length = 0;
}
proto_item_set_len(pitem, length);
if (length == 0)
proto_item_append_text(pitem, ": MISSING");
if (next_tree) *next_tree = proto_item_add_subtree(pitem, ett_btsdp_data_element_value);
offset += length;
return offset;
}
static gint
findDidVendorIdSource(tvbuff_t *tvb, gint service_offset,
gint number_of_attributes)
{
gint result = 0;
gint search_length;
gint search_offset;
gint i_number_of_attributes;
guint16 attribute;
search_offset = service_offset;
i_number_of_attributes = 0;
while (i_number_of_attributes < number_of_attributes) {
search_offset = get_type_length(tvb, search_offset, &search_length);
attribute = tvb_get_ntohs(tvb, search_offset);
search_offset += search_length;
search_offset = get_type_length(tvb, search_offset, &search_length);
if (attribute == 0x205) {
result = get_uint_by_size(tvb, search_offset, 1);
}
search_offset += search_length;
i_number_of_attributes += 1;
}
return result;
}
static gint
findDidVendorId(tvbuff_t *tvb, gint service_offset,
gint number_of_attributes)
{
gint result = 0;
gint search_length;
gint search_offset;
gint i_number_of_attributes;
guint16 attribute;
search_offset = service_offset;
i_number_of_attributes = 0;
while (i_number_of_attributes < number_of_attributes) {
search_offset = get_type_length(tvb, search_offset, &search_length);
attribute = tvb_get_ntohs(tvb, search_offset);
search_offset += search_length;
search_offset = get_type_length(tvb, search_offset, &search_length);
if (attribute == 0x201) {
result = get_uint_by_size(tvb, search_offset, 1);
}
search_offset += search_length;
i_number_of_attributes += 1;
}
return result;
}
static void
dissect_protocol_descriptor_list(proto_tree *next_tree, tvbuff_t *tvb,
packet_info *pinfo, gint offset, gint size, wmem_strbuf_t *info_buf,
service_info_t *service_info, gint *protocol_order)
{
proto_tree *feature_tree;
proto_item *feature_item;
proto_tree *entry_tree;
proto_item *entry_item;
proto_tree *sub_tree;
proto_tree *last_tree;
gint new_offset;
gint list_offset;
gint entry_offset;
gint entry_length;
guint32 value;
gint length;
guint32 i_protocol;
uuid_t uuid;
service_info_t *record = NULL;
list_offset = offset;
i_protocol = 1;
while (list_offset - offset < size) {
gchar *uuid_str;
feature_item = proto_tree_add_none_format(next_tree, hf_sdp_protocol_item, tvb, list_offset, 0, "Protocol #%u", i_protocol);
feature_tree = proto_item_add_subtree(feature_item, ett_btsdp_protocol);
entry_offset = get_type_length(tvb, list_offset, &entry_length);
proto_item_set_len(feature_item, entry_length + (entry_offset - list_offset));
dissect_data_element(feature_tree, &sub_tree, pinfo, tvb, list_offset);
entry_item = proto_tree_add_item(sub_tree, hf_sdp_protocol, tvb, entry_offset, entry_length, ENC_NA);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_id);
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
entry_offset = new_offset;
dissect_uuid(sub_tree, tvb, entry_offset, length, &uuid);
uuid_str = print_uuid(&uuid);
wmem_strbuf_append(info_buf, uuid_str);
proto_item_append_text(feature_item, ": %s", uuid_str);
proto_item_append_text(entry_item, ": %s", uuid_str);
entry_offset += length;
if (entry_offset - list_offset <= entry_length) {
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
entry_offset = new_offset;
value = get_int_by_size(tvb, entry_offset, length / 2);
if (uuid.bt_uuid == BTSDP_L2CAP_PROTOCOL_UUID) {
wmem_strbuf_append_printf(info_buf, ":%u", value);
proto_item_append_text(feature_item, ", PSM: %u", value);
proto_item_append_text(entry_item, ", PSM: %u", value);
proto_tree_add_item(sub_tree, hf_sdp_protocol_psm, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
if (!pinfo->fd->flags.visited && service_info)
record = save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, value, *protocol_order, service_info);
*protocol_order += 1;
} else if (uuid.bt_uuid == BTSDP_RFCOMM_PROTOCOL_UUID) {
wmem_strbuf_append_printf(info_buf, ":%u", value);
proto_item_append_text(feature_item, ", RFCOMM Channel: %u", value);
proto_item_append_text(entry_item, ", RFCOMM Channel: %u", value);
proto_tree_add_item(sub_tree, hf_sdp_protocol_channel, tvb, entry_offset, 1, ENC_BIG_ENDIAN);
if (!pinfo->fd->flags.visited && service_info)
record = save_channel(pinfo, BTSDP_RFCOMM_PROTOCOL_UUID, value, *protocol_order, service_info);
*protocol_order += 1;
} else if (uuid.bt_uuid == BTSDP_ATT_PROTOCOL_UUID) {
proto_item_append_text(feature_item, ", GATT Handle Start: 0x%04x", value);
proto_item_append_text(entry_item, ", GATT Handle Start: 0x%04x", value);
wmem_strbuf_append_printf(info_buf, ":0x%04x.", value);
proto_tree_add_item(sub_tree, hf_sdp_protocol_gatt_handle_start, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
if ((entry_offset - list_offset) + length <= entry_length) {
entry_offset += length;
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
entry_offset = new_offset;
value = get_int_by_size(tvb, entry_offset, length / 2);
wmem_strbuf_append_printf(info_buf, ".0x%04x", value);
proto_item_append_text(feature_item, ", GATT Handle End: 0x%04x", value);
proto_item_append_text(entry_item, ", GATT Handle End: 0x%04x", value);
proto_tree_add_item(sub_tree, hf_sdp_protocol_gatt_handle_end, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
}
} else {
wmem_strbuf_append_printf(info_buf, " (%x.%x)", value >> 8, value & 0xFF);
proto_item_append_text(feature_item, ", Version %x.%x", value >> 8, value & 0xFF);
proto_item_append_text(entry_item, ", Version 0x%03x", value);
proto_tree_add_item(sub_tree, hf_sdp_protocol_version, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
}
entry_offset += length;
}
while (entry_offset - list_offset <= entry_length) {
gint value_offset;
gint len;
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
if (uuid.bt_uuid == BTSDP_BNEP_PROTOCOL_UUID) {
wmem_strbuf_append(info_buf, " (");
value_offset = new_offset;
while (value_offset - new_offset < length) {
gint next_offset;
dissect_data_element(sub_tree, &last_tree, pinfo, tvb, value_offset);
next_offset = get_type_length(tvb, value_offset, &len);
value = get_int_by_size(tvb, next_offset, len / 2);
proto_tree_add_item(last_tree, hf_sdp_protocol_bnep_type, tvb, next_offset, 2, ENC_BIG_ENDIAN);
wmem_strbuf_append(info_buf, val_to_str_const(value, etype_vals, "Unknown"));
value_offset = next_offset + len;
if (value_offset - new_offset < length)
wmem_strbuf_append(info_buf, " ");
}
wmem_strbuf_append(info_buf, ")");
}
entry_offset = new_offset + length;
}
i_protocol += 1;
list_offset = entry_offset;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, " -> ");
if (record)
record->protocol = uuid.bt_uuid;
}
}
static gint
dissect_sdp_type(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
gint offset, gint attribute, uuid_t service_uuid,
gint service_did_vendor_id, gint service_did_vendor_id_source,
service_info_t *service_info, wmem_strbuf_t **pinfo_buf)
{
proto_tree *feature_tree;
proto_item *feature_item;
proto_tree *entry_tree;
proto_item *entry_item;
proto_tree *next_tree;
proto_tree *sub_tree;
proto_tree *last_tree;
gint size;
guint8 byte;
guint8 type;
guint8 size_index;
gint start_offset;
gint new_offset;
gint list_offset;
gint list_length;
gint entry_offset;
gint entry_length;
gboolean found;
guint16 specification_id;
guint16 vendor_id;
guint16 product_id;
guint16 version;
guint8 primary_record;
guint8 mdep_id;
guint16 vendor_id_source;
const guint8 *str_val;
guint16 supported_features;
guint i_feature;
guint i_protocol;
guint16 psm;
guint8 *new_str;
guint32 value;
guint64 value_64;
uuid_t uuid;
gchar *uuid_str;
gint length;
gint protocol_order;
wmem_strbuf_t *info_buf;
info_buf = wmem_strbuf_new_label(wmem_packet_scope());
*pinfo_buf = info_buf;
byte = tvb_get_guint8(tvb, offset);
type = (byte >> 3) & 0x1f;
size_index = byte & 0x07;
start_offset = offset;
new_offset = dissect_data_element(tree, &next_tree, pinfo, tvb, offset);
offset = get_type_length(tvb, offset, &size);
found = TRUE;
switch(service_uuid.bt_uuid) {
case BTSDP_DID_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_did_specification_id, tvb, offset, 2, ENC_BIG_ENDIAN);
specification_id = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%x.%02x (0x%04x)", specification_id >> 8, specification_id & 0xFF, specification_id);
break;
case 0x201:
vendor_id = tvb_get_ntohs(tvb, offset);
if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_BLUETOOTH_SIG) {
proto_tree_add_item(next_tree, hf_did_vendor_id_bluetooth_sig, tvb, offset, 2, ENC_BIG_ENDIAN);
str_val = val_to_str_ext_const(vendor_id, &bthci_evt_comp_id_ext, "Unknown");
} else if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
proto_tree_add_item(next_tree, hf_did_vendor_id_usb_forum, tvb, offset, 2, ENC_BIG_ENDIAN);
str_val = val_to_str_ext_const(vendor_id, &ext_usb_vendors_vals, "Unknown");
} else {
proto_tree_add_item(next_tree, hf_did_vendor_id, tvb, offset, 2, ENC_BIG_ENDIAN);
str_val = "Unknown";
}
wmem_strbuf_append_printf(info_buf, "%s (0x%04x)", str_val, vendor_id);
break;
case 0x202:
entry_item = proto_tree_add_item(next_tree, hf_did_product_id, tvb, offset, 2, ENC_BIG_ENDIAN);
product_id = tvb_get_ntohs(tvb, offset);
if (service_did_vendor_id_source == DID_VENDOR_ID_SOURCE_USB_FORUM) {
str_val = val_to_str_ext_const(service_did_vendor_id << 16 | product_id, &ext_usb_products_vals, "Unknown");
wmem_strbuf_append_printf(info_buf, "%s (0x%04x)", str_val, product_id);
proto_item_append_text(entry_item, " (%s)", str_val);
} else {
wmem_strbuf_append_printf(info_buf, "0x%04x", product_id);
}
break;
case 0x203:
proto_tree_add_item(next_tree, hf_did_version, tvb, offset, 2, ENC_BIG_ENDIAN);
version = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
break;
case 0x204:
proto_tree_add_item(next_tree, hf_did_primary_record, tvb, offset, 1, ENC_BIG_ENDIAN);
primary_record = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, primary_record ? "true" : "false");
break;
case 0x205:
proto_tree_add_item(next_tree, hf_did_vendor_id_source, tvb, offset, 2, ENC_BIG_ENDIAN);
vendor_id_source = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s (0x%04x)",
val_to_str_const(vendor_id_source, did_vendor_id_source_vals, "Unknown"),
vendor_id_source);
break;
default:
found = FALSE;
}
break;
case BTSDP_A2DP_SINK_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_amplifier, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_recorder, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_speaker, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_sink_supported_features_headphone, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
(supported_features & 0x01) ? "Headphone " : "",
(supported_features & 0x02) ? "Speaker " : "",
(supported_features & 0x04) ? "Recorder " : "",
(supported_features & 0x08) ? "Amplifier " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_A2DP_SOURCE_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_mixer, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_tuner, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_microphone, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_a2dp_source_supported_features_player, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
(supported_features & 0x01) ? "Player " : "",
(supported_features & 0x02) ? "Microphone " : "",
(supported_features & 0x04) ? "Tuner " : "",
(supported_features & 0x08) ? "Mixer " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_SYNC_SERVICE_UUID:
switch (attribute) {
case 0x301:
list_offset = offset;
while (list_offset - offset < size) {
dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &list_length);
proto_tree_add_item(entry_tree, hf_synch_supported_data_store, tvb, list_offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, "%s ", val_to_str_const(value, synch_supported_data_store_vals, "Unknown"));
list_offset += list_length;
}
break;
default:
found = FALSE;
}
break;
case BTSDP_CTP_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_ctp_external_network, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, ctp_external_network_vals, "Unknown"));
break;
default:
found = FALSE;
}
break;
case BTSDP_AVRCP_SERVICE_UUID:
case BTSDP_AVRCP_CT_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_reserved_7_15, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_browsing, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_reserved_4_5, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_4, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_3, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_2, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_ct_supported_features_category_1, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s",
(supported_features & 0x01) ? "Category1(Player/Recorder) " : "",
(supported_features & 0x02) ? "Category2(Monitor/Amplifier) " : "",
(supported_features & 0x04) ? "Category3(Tuner) " : "",
(supported_features & 0x08) ? "Category4(Menu) " : "",
(supported_features & 0x40) ? "Browsing " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_AVRCP_TG_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_reserved_8_15, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_multiple_player, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_browsing, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_group_navigation, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_settings, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_4, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_3, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_2, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_avrcp_tg_supported_features_category_1, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s",
(supported_features & 0x01) ? "Category1(Player/Recorder) " : "",
(supported_features & 0x02) ? "Category2(Monitor/Amplifier) " : "",
(supported_features & 0x04) ? "Category3(Tuner) " : "",
(supported_features & 0x08) ? "Category4(Menu) " : "",
(supported_features & 0x10) ? "PlayerApplicationSettings " : "",
(supported_features & 0x20) ? "GroupNavigation " : "",
(supported_features & 0x40) ? "Browsing " : "",
(supported_features & 0x80) ? "MultiplePlayers " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_HSP_SERVICE_UUID:
case BTSDP_HSP_HS_SERVICE_UUID:
switch (attribute) {
case 0x302:
proto_tree_add_item(next_tree, hf_hsp_remote_audio_volume_control, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
default:
found = FALSE;
}
break;
case BTSDP_GNSS_UUID:
case BTSDP_GNSS_SERVER_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_gnss_supported_features, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "reserved (0x%04x)", supported_features);
break;
default:
found = FALSE;
}
break;
case BTSDP_PBAP_PSE_SERVICE_UUID:
switch (attribute) {
case 0x314:
proto_tree_add_item(next_tree, hf_pbap_pse_supported_repositories_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_pbap_pse_supported_repositories_sim_card, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_pbap_pse_supported_repositories_local_phonebook, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s",
(supported_features & 0x01) ? "LocalPhonebook " : "",
(supported_features & 0x02) ? "SIM " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_FAX_SERVICE_UUID:
switch (attribute) {
case 0x302:
proto_tree_add_item(next_tree, hf_fax_support_class_1, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
break;
case 0x303:
proto_tree_add_item(next_tree, hf_fax_support_class_2, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
break;
case 0x304:
proto_tree_add_item(next_tree, hf_fax_support_class_2_vendor, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
break;
case 0x305:
proto_tree_add_item(next_tree, hf_fax_support_audio_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
break;
default:
found = FALSE;
}
break;
case BTSDP_FTP_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_ftp_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN);
psm = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
if (!pinfo->fd->flags.visited && service_info)
save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
break;
default:
found = FALSE;
}
break;
case BTSDP_MAP_SERVICE_UUID:
case BTSDP_MAP_ACCESS_SRV_SERVICE_UUID:
switch (attribute) {
case 0x315:
proto_tree_add_item(next_tree, hf_map_mas_instance_id, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", value, value);
break;
case 0x316:
proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_sms_cdma, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_sms_gsm, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_map_mas_supported_message_types_email, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
(supported_features & 0x01) ? "Email " : "",
(supported_features & 0x02) ? "SMS_GSM " : "",
(supported_features & 0x04) ? "SMS_CDMA " : "",
(supported_features & 0x08) ? "MMS " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_HCRP_SERVICE_UUID:
case BTSDP_HCRP_PRINT_SERVICE_UUID:
case BTSDP_HCRP_SCAN_SERVICE_UUID:
switch (attribute) {
case 0x300:
proto_tree_add_item(next_tree, hf_hcrp_1284_id, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x302:
proto_tree_add_item(next_tree, hf_hcrp_device_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x304:
proto_tree_add_item(next_tree, hf_hcrp_friendly_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x306:
proto_tree_add_item(next_tree, hf_hcrp_device_location, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
case BTSDP_WAP_SERVICE_UUID:
case BTSDP_WAP_CLIENT_SERVICE_UUID:
switch (attribute) {
case 0x306:
proto_tree_add_item(next_tree, hf_wap_network_address, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append(info_buf, ip_to_str((guint8 *)&value));
break;
case 0x307:
proto_tree_add_item(next_tree, hf_wap_gateway, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, wap_gateway_vals, "Unknown"));
break;
case 0x308:
proto_tree_add_item(next_tree, hf_wap_homepage_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x309:
proto_tree_add_item(next_tree, hf_wap_stack_type, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, wap_stack_type_vals, "Unknown"));
break;
default:
found = FALSE;
}
break;
case BTSDP_HDP_SERVICE_UUID:
case BTSDP_HDP_SOURCE_SERVICE_UUID:
case BTSDP_HDP_SINK_SERVICE_UUID:
switch (attribute) {
case 0x200:
i_feature = 1;
list_offset = offset;
while (list_offset - offset < size) {
entry_offset = get_type_length(tvb, list_offset, &entry_length);
feature_item = proto_tree_add_none_format(next_tree, hf_hdp_supported_features_data, tvb, entry_offset, entry_length, "Supported Feature #%u", i_feature);
feature_tree = proto_item_add_subtree(feature_item, ett_btsdp_supported_features);
dissect_data_element(feature_tree, &sub_tree, pinfo, tvb, list_offset);
entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_id, tvb, entry_offset, 0, ENC_NA);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_id);
dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
entry_offset = new_offset;
proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_id, tvb, entry_offset, 1, ENC_BIG_ENDIAN);
mdep_id = tvb_get_guint8(tvb, entry_offset);
proto_item_append_text(entry_item, ": %u (0x%02x)", mdep_id, mdep_id);
entry_offset += length;
entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_data_type, tvb, entry_offset, 0, ENC_NA);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_data_type);
dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
entry_offset = new_offset;
proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_data_type, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, entry_offset);
proto_item_append_text(entry_item, ": %u (0x%04x)", value, value);
entry_offset += length;
entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_role, tvb, entry_offset, 0, ENC_NA);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_role);
dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
entry_offset = new_offset;
proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_role, tvb, entry_offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, entry_offset);
wmem_strbuf_append_printf(info_buf, "MDEP ID: %u (Role: %s) ", mdep_id, val_to_str_const(value, hdp_mdep_role_vals ,"Unknown"));
proto_item_append_text(entry_item, ": %s", val_to_str_const(value, hdp_mdep_role_vals ,"Unknown"));
entry_offset += length;
if (entry_length - (entry_offset - list_offset) > 0) {
entry_item = proto_tree_add_item(sub_tree, hf_hdp_supported_features_data_mdep_description, tvb, entry_offset, entry_length, ENC_NA);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_supported_features_mdep_description);
dissect_data_element(entry_tree, &next_tree, pinfo, tvb, entry_offset);
new_offset = get_type_length(tvb, entry_offset, &length);
proto_item_set_len(entry_item, (new_offset - entry_offset) + length);
entry_offset = new_offset;
proto_tree_add_item(next_tree, hf_hdp_supported_features_mdep_description, tvb, entry_offset, length, ENC_ASCII | ENC_NA);
proto_item_append_text(entry_item, ": %s", tvb_get_string(wmem_packet_scope(), tvb, entry_offset, length));
entry_offset += length;
}
list_offset = entry_offset;
i_feature += 1;
}
break;
case 0x301:
proto_tree_add_item(next_tree, hf_hdp_data_exchange, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, hdp_data_exchange_specification_vals, "Unknown"));
break;
case 0x302:
proto_tree_add_item(next_tree, hf_hdp_support_procedure_reserved_5_7, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hdp_support_procedure_sync_master_role, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hdp_support_procedure_clock_synchronization_protocol, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hdp_support_procedure_reconnect_acceptance, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hdp_support_procedure_reconnect_initiation, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hdp_support_procedure_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
(supported_features & 0x02) ? "ReconnectInitiation " : "",
(supported_features & 0x04) ? "ReconnectAcceptance " : "",
(supported_features & 0x08) ? "ClockSynchronizationProtocol " : "",
(supported_features & 0x10) ? "SyncMasterRole " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_PAN_GN_SERVICE_UUID:
switch (attribute) {
case 0x30A:
proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
break;
case 0x30D:
case 0x200:
proto_tree_add_item(next_tree, hf_pan_ipv4_subnet, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x30E:
proto_tree_add_item(next_tree, hf_pan_ipv6_subnet, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
case BTSDP_PAN_NAP_SERVICE_UUID:
switch (attribute) {
case 0x30A:
proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
break;
case 0x30B:
proto_tree_add_item(next_tree, hf_pan_net_access_type, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, pan_net_access_type_vals, "Unknown"));
break;
case 0x30C:
proto_tree_add_item(next_tree, hf_pan_max_net_access_rate, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%08x)", value, value);
break;
case 0x30D:
case 0x200:
proto_tree_add_item(next_tree, hf_pan_ipv4_subnet, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x30E:
proto_tree_add_item(next_tree, hf_pan_ipv6_subnet, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
case BTSDP_PAN_PANU_SERVICE_UUID:
switch (attribute) {
case 0x30A:
proto_tree_add_item(next_tree, hf_pan_sercurity_description, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, pan_security_description_vals, "Unknown"));
break;
default:
found = FALSE;
}
break;
case BTSDP_OPP_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_opp_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN);
psm = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
if (!pinfo->fd->flags.visited && service_info)
save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
break;
case 0x303:
list_offset = offset;
while (list_offset - offset < size) {
dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &list_length);
proto_tree_add_item(entry_tree, hf_opp_supported_format, tvb, list_offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, "%s ", val_to_str_const(value, opp_supported_format_vals, "Unknown"));
list_offset += list_length;
}
break;
default:
found = FALSE;
}
break;
case BTSDP_DUN_SERVICE_UUID:
switch (attribute) {
case 0x305:
proto_tree_add_item(next_tree, hf_dun_support_audio_feedback, tvb, offset, 1, ENC_BIG_ENDIAN);
supported_features = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, supported_features ? "true" : "false");
break;
case 0x306:
proto_tree_add_item(next_tree, hf_dun_escape_sequence, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
case BTSDP_HFP_SERVICE_UUID:
switch (attribute) {
case 0x311:
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_wide_band_speech, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_remote_volume_control, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_voice_recognition_activation, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_cli_presentation_capability, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_call_waiting_or_three_way_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_hf_supported_features_ec_and_or_nr_function, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s",
(supported_features & 0x01) ? "(EC and/or Nr Function) " : "",
(supported_features & 0x02) ? "(Call Waiting or Three Way Calling) " : "",
(supported_features & 0x04) ? "(CLI Presentation Capability) " : "",
(supported_features & 0x08) ? "(Voice Recognition Activation) " : "",
(supported_features & 0x10) ? "(Remote Volume Control) " : "",
(supported_features & 0x20) ? "(Wide Band Speech) " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_HFP_GW_SERVICE_UUID:
switch (attribute) {
case 0x301:
proto_tree_add_item(next_tree, hf_hfp_gw_network, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, hfp_gw_network_vals, "Unknown"));
break;
case 0x311:
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_wide_band_speech, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_inband_ring_tone_capability, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_voice_recognition_function, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_ec_and_or_nr_function, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hfp_gw_supported_features_three_way_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
supported_features = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s",
(supported_features & 0x01) ? "(Three Way Calling) " : "",
(supported_features & 0x02) ? "(EC and/or Nr Function) " : "",
(supported_features & 0x04) ? "(Voice Recognition Function) " : "",
(supported_features & 0x08) ? "(Inband Ring Tone Capability) " : "",
(supported_features & 0x10) ? "(Attach a Phone Number to a Voice Tag) " : "",
(supported_features & 0x20) ? "(Wide Band Speech) " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_HID_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_hid_device_release_number, tvb, offset, 2, ENC_BIG_ENDIAN);
version = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
break;
case 0x201:
proto_tree_add_item(next_tree, hf_hid_parser_version, tvb, offset, 2, ENC_BIG_ENDIAN);
version = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
break;
case 0x202:
proto_tree_add_item(next_tree, hf_hid_device_subclass_type, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hid_device_subclass_subtype, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_hid_device_subclass_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s, %s",
val_to_str_const(value >> 6, hid_device_subclass_type_vals, "Unknown"),
val_to_str_const(((value & 0x3C) >> 2) , hid_device_subclass_subtype_vals, "Unknown"));
break;
case 0x203:
proto_tree_add_item(next_tree, hf_hid_country_code, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, hid_country_code_vals, "Unknown"));
break;
case 0x204:
proto_tree_add_item(next_tree, hf_hid_virtual_cable, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x205:
proto_tree_add_item(next_tree, hf_hid_reconnect_initiate, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x206:
list_offset = offset;
i_feature = 1;
while (list_offset - offset < size) {
entry_item = proto_tree_add_none_format(next_tree, hf_hid_descriptor_list_descriptor_data, tvb, list_offset, size, "Descriptor #%u", i_feature);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
proto_tree_add_item(last_tree, hf_hid_descriptor_list_type, tvb, list_offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, list_offset);
wmem_strbuf_append(info_buf, val_to_str_const(value, descriptor_list_type_vals, "Unknown"));
proto_item_append_text(entry_item, ": %s", val_to_str_const(value, descriptor_list_type_vals, "Unknown"));
list_offset += entry_length;
dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
proto_tree_add_item(last_tree, hf_hid_descriptor_list_descriptor, tvb, list_offset, entry_length, ENC_NA);
list_offset += entry_length;
i_feature += 1;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, ", ");
}
break;
case 0x207:
list_offset = offset;
i_feature = 1;
while (list_offset - offset < size) {
wmem_strbuf_append(info_buf, "[");
entry_item = proto_tree_add_none_format(next_tree, hf_hid_lang, tvb, list_offset, size, "Language #%u", i_feature);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
value = tvb_get_ntohs(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, "Lang ID: %s", val_to_str_ext_const(value, &usb_langid_vals_ext, "Unknown"));
proto_item_append_text(entry_item, ": Lang ID: %s", val_to_str_ext_const(value, &usb_langid_vals_ext, "Unknown"));
proto_tree_add_item(last_tree, hf_sdp_lang_id, tvb, list_offset, entry_length, ENC_ASCII | ENC_NA);
list_offset += entry_length;
dissect_data_element(sub_tree, &last_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
value = tvb_get_ntohs(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, ", Attribute Base: 0x%04x", value);
proto_item_append_text(entry_item, ", Attribute Base: 0x%04x", value);
proto_tree_add_item(last_tree, hf_sdp_lang_attribute_base, tvb, list_offset, 2, ENC_BIG_ENDIAN);
list_offset += entry_length;
i_feature += 1;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, "], ");
else
wmem_strbuf_append(info_buf, "]");
}
break;
case 0x208:
proto_tree_add_item(next_tree, hf_hid_sdp_disable, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x209:
proto_tree_add_item(next_tree, hf_hid_battery_power, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x20A:
proto_tree_add_item(next_tree, hf_hid_remote_wake, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x20B:
proto_tree_add_item(next_tree, hf_hid_profile_version, tvb, offset, 2, ENC_BIG_ENDIAN);
version = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%x.%x.%x (0x%04x)", version >> 8, (version >> 4) & 0xF, version & 0xF, version);
break;
case 0x20C:
proto_tree_add_item(next_tree, hf_hid_supervision_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u", value);
break;
case 0x20D:
proto_tree_add_item(next_tree, hf_hid_normally_connectable, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x20E:
proto_tree_add_item(next_tree, hf_hid_boot_device, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x20F:
proto_tree_add_item(next_tree, hf_hid_ssr_host_max_latency, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u", value);
break;
case 0x210:
proto_tree_add_item(next_tree, hf_hid_ssr_host_min_timeout, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u", value);
break;
default:
found = FALSE;
}
break;
case BTSDP_BIP_SERVICE_UUID:
case BTSDP_BIP_RESPONDER_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN);
psm = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
if (!pinfo->fd->flags.visited && service_info)
save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
break;
case 0x310:
proto_tree_add_item(next_tree, hf_bip_supported_capabilities_reserved_4_7, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_capabilities_displaying, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_capabilities_printing, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_capabilities_capturing, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_capabilities_genering_imaging, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s",
(value & 0x01) ? "GeneringImaging " : "",
(value & 0x02) ? "Capturing " : "",
(value & 0x04) ? "Printing " : "",
(value & 0x08) ? "Displaying " : "");
break;
case 0x311:
proto_tree_add_item(next_tree, hf_bip_supported_features_reserved_9_15, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_remote_display, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_remote_camera, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_automatic_archive, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_advanced_image_printing, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_image_pull, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_display, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_print, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_image_push_store, tvb, offset, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_features_image_push, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s",
(value & 0x001) ? "ImagePush " : "",
(value & 0x002) ? "ImagePushStore " : "",
(value & 0x004) ? "ImagePushPrint " : "",
(value & 0x008) ? "ImagePushDisplay " : "",
(value & 0x010) ? "ImagePull " : "",
(value & 0x020) ? "AdvancedImagePrinting " : "",
(value & 0x040) ? "AutomatingArchive " : "",
(value & 0x080) ? "RemoteCamera " : "",
(value & 0x100) ? "RemoteDisplay " : "");
break;
case 0x312:
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_17_31, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_status, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_15, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_monitoring_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_start_archive, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_12, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_start_print, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_delete_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image_property, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_images_list, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_remote_display, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_put_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_put_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_put_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(value & 0x001) ? "GetCapabilities " : "",
(value & 0x002) ? "PutImage " : "",
(value & 0x004) ? "PutLinkedAttachment " : "",
(value & 0x008) ? "PutLinkedThumbnail " : "",
(value & 0x010) ? "RemoteDisplay " : "",
(value & 0x020) ? "GetImageList " : "",
(value & 0x040) ? "GetImageProperty " : "",
(value & 0x080) ? "GetImage " : "",
(value & 0x100) ? "GetLinkedThumbnail " : "",
(value & 0x200) ? "GetLinkedAttachment " : "",
(value & 0x400) ? "DeleteImage " : "",
(value & 0x800) ? "StartPrint " : "",
(value & 0x2000) ? "StartArchive " : "",
(value & 0x4000) ? "GetMonitoringImage " : "",
(value & 0x10000) ? "GetStatus " : "");
break;
case 0x313:
proto_tree_add_item(next_tree, hf_bip_total_imaging_data_capacity, tvb, offset, 8, ENC_BIG_ENDIAN);
value_64 = tvb_get_ntoh64(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%"G_GUINT64_FORMAT, value_64);
break;
default:
found = FALSE;
}
break;
case BTSDP_BIP_REF_OBJ_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN);
psm = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
if (!pinfo->fd->flags.visited && service_info)
save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
break;
case 0x312:
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_13_31, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_partial_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_1_11, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s",
(value & 0x0001) ? "GetCapabilities " : "",
(value & 0x1000) ? "GetPartialImage " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_BIP_AUTO_ARCH_SERVICE_UUID:
switch (attribute) {
case 0x200:
proto_tree_add_item(next_tree, hf_bip_goep_l2cap_psm, tvb, offset, 2, ENC_BIG_ENDIAN);
psm = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%02x)", psm, psm);
if (!pinfo->fd->flags.visited)
save_channel(pinfo, BTSDP_L2CAP_PROTOCOL_UUID, psm, -1, service_info);
break;
case 0x312:
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_11_31, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_delete_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_attachment, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_linked_thumbnail, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_image_property, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_images_list, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_reserved_1_4, tvb, offset, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(next_tree, hf_bip_supported_functions_get_capabilities, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%s%s%s%s%s%s%s",
(value & 0x001) ? "GetCapabilities " : "",
(value & 0x020) ? "GetImageList " : "",
(value & 0x040) ? "GetImageProperty " : "",
(value & 0x080) ? "GetImage " : "",
(value & 0x100) ? "GetLinkedThumbnail " : "",
(value & 0x200) ? "GetLinkedAttachment " : "",
(value & 0x400) ? "DeleteImage " : "");
break;
default:
found = FALSE;
}
break;
case BTSDP_BPP_SERVICE_UUID:
case BTSDP_BPP_STATUS_SERVICE_UUID:
case BTSDP_BPP_DIRECT_PRINTING_SERVICE_UUID:
case BTSDP_BPP_REFERENCE_PRINTING_SERVICE_UUID:
switch (attribute) {
case 0x350:
proto_tree_add_item(next_tree, hf_bpp_document_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x352:
proto_tree_add_item(next_tree, hf_bpp_character_repertoires_support, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_bytes_to_ep_str(tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x354:
proto_tree_add_item(next_tree, hf_bpp_xhtml_print_image_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x356:
proto_tree_add_item(next_tree, hf_bpp_color_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x358:
proto_tree_add_item(next_tree, hf_bpp_1284_id, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x35A:
proto_tree_add_item(next_tree, hf_bpp_printer_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x35C:
proto_tree_add_item(next_tree, hf_bpp_printer_location, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x35E:
proto_tree_add_item(next_tree, hf_bpp_duplex_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x360:
proto_tree_add_item(next_tree, hf_bpp_media_types_supported, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x362:
proto_tree_add_item(next_tree, hf_bpp_max_media_width, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u", value);
break;
case 0x364:
proto_tree_add_item(next_tree, hf_bpp_max_media_length, tvb, offset, 2, ENC_BIG_ENDIAN);
value = tvb_get_ntohs(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u", value);
break;
case 0x366:
proto_tree_add_item(next_tree, hf_bpp_enhanced_layout_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x368:
proto_tree_add_item(next_tree, hf_bpp_rui_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x370:
proto_tree_add_item(next_tree, hf_bpp_reference_printing_rui_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x372:
proto_tree_add_item(next_tree, hf_bpp_direct_printing_rui_supported, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append(info_buf, value ? "true" : "false");
break;
case 0x374:
proto_tree_add_item(next_tree, hf_bpp_reference_printing_top_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x376:
proto_tree_add_item(next_tree, hf_bpp_direct_printing_top_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x37A:
proto_tree_add_item(next_tree, hf_bpp_device_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
case BTSDP_BPP_REFLECTED_UI_SERVICE_UUID:
switch (attribute) {
case 0x368:
proto_tree_add_item(next_tree, hf_bpp_rui_formats_supported, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x378:
proto_tree_add_item(next_tree, hf_bpp_printer_admin_rui_top_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
break;
default:
found = FALSE;
}
if (!found) {
found = TRUE;
switch (attribute) {
case 0x000:
proto_tree_add_item(next_tree, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "0x%08x (%u)", value, value);
break;
case 0x001:
list_offset = offset;
while (list_offset - offset < size) {
dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &list_length);
dissect_uuid(entry_tree, tvb, list_offset, list_length, &uuid);
wmem_strbuf_append(info_buf, print_uuid(&uuid));
list_offset += list_length;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, " -> ");
}
break;
case 0x002:
proto_tree_add_item(next_tree, hf_sdp_service_record_state, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "0x%08x (%u)", value, value);
break;
case 0x003:
dissect_uuid(next_tree, tvb, offset, size, &uuid);
wmem_strbuf_append(info_buf, print_uuid(&uuid));
break;
case 0x004:
protocol_order = 0;
dissect_protocol_descriptor_list(next_tree, tvb, pinfo,
offset, size, info_buf, service_info, &protocol_order);
break;
case 0x005:
list_offset = offset;
while (list_offset - offset < size) {
dissect_data_element(next_tree, &entry_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &list_length);
dissect_uuid(entry_tree, tvb, list_offset, list_length, &uuid);
wmem_strbuf_append(info_buf, print_uuid(&uuid));
list_offset += list_length;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, ", ");
}
break;
case 0x006:
list_offset = offset;
i_feature = 1;
while (list_offset - offset < size) {
wmem_strbuf_append(info_buf, "(");
entry_item = proto_tree_add_none_format(next_tree, hf_sdp_lang, tvb, list_offset, size, "Language #%u", i_feature);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
new_str = tvb_get_string(wmem_packet_scope(), tvb, list_offset, entry_length);
wmem_strbuf_append_printf(info_buf, "Lang: %s", new_str);
proto_item_append_text(entry_item, ": Lang: %s", new_str);
proto_tree_add_item(sub_tree, hf_sdp_lang_code, tvb, list_offset, entry_length, ENC_ASCII | ENC_NA);
list_offset += entry_length;
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
value = tvb_get_ntohs(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, ", Encoding: %s", val_to_str_ext_const(value, &wap_mib_enum_vals_character_sets_ext, "Unknown"));
proto_item_append_text(entry_item, ", Encoding: %s", val_to_str_ext_const(value, &wap_mib_enum_vals_character_sets_ext, "Unknown"));
proto_tree_add_item(sub_tree, hf_sdp_lang_encoding, tvb, list_offset, 2, ENC_BIG_ENDIAN);
list_offset += entry_length;
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, list_offset);
list_offset = get_type_length(tvb, list_offset, &entry_length);
value = tvb_get_ntohs(tvb, list_offset);
wmem_strbuf_append_printf(info_buf, ", Attribute Base: 0x%04x", value);
proto_item_append_text(entry_item, ", Attribute Base: 0x%04x", value);
proto_tree_add_item(sub_tree, hf_sdp_lang_attribute_base, tvb, list_offset, 2, ENC_BIG_ENDIAN);
list_offset += entry_length;
i_feature += 1;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, "), ");
else
wmem_strbuf_append(info_buf, ")");
}
break;
case 0x007:
proto_tree_add_item(next_tree, hf_sdp_service_info_time_to_live, tvb, offset, 4, ENC_BIG_ENDIAN);
value = tvb_get_ntohl(tvb, offset);
wmem_strbuf_append_printf(info_buf, "%u (0x%08x)", value, value);
break;
case 0x008:
proto_tree_add_item(next_tree, hf_sdp_service_availability, tvb, offset, 1, ENC_BIG_ENDIAN);
value = tvb_get_guint8(tvb, offset);
wmem_strbuf_append_printf(info_buf, "0x%02x (%u)", value, value);
break;
case 0x009:
list_offset = offset;
i_protocol = 1;
while (list_offset - offset < size) {
entry_offset = get_type_length(tvb, list_offset, &entry_length);
dissect_data_element(next_tree, &sub_tree, pinfo, tvb, list_offset);
entry_item = proto_tree_add_none_format(sub_tree, hf_profile_descriptor_list, tvb, entry_offset, entry_length, "Profile Descriptor List #%u", i_protocol);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
entry_offset = get_type_length(tvb, entry_offset, &entry_length);
dissect_uuid(sub_tree, tvb, entry_offset, entry_length, &uuid);
uuid_str = print_uuid(&uuid);
wmem_strbuf_append(info_buf, uuid_str);
proto_item_append_text(entry_item, ": %s", uuid_str);
entry_offset += entry_length;
dissect_data_element(entry_tree, &sub_tree, pinfo, tvb, entry_offset);
entry_offset = get_type_length(tvb, entry_offset, &entry_length);
value = tvb_get_ntohs(tvb, entry_offset);
wmem_strbuf_append_printf(info_buf, " %x.%x", value >> 8, value & 0xFF);
proto_item_append_text(entry_item, ", Version %x.%x", value >> 8, value & 0xFF);
proto_tree_add_item(sub_tree, hf_sdp_protocol_version, tvb, entry_offset, 2, ENC_BIG_ENDIAN);
entry_offset += entry_length;
list_offset = entry_offset;
if (list_offset - offset < size)
wmem_strbuf_append(info_buf, ", ");
i_protocol += 1;
}
break;
case 0x00A:
proto_tree_add_item(next_tree, hf_sdp_service_documentation_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x00B:
proto_tree_add_item(next_tree, hf_sdp_service_client_executable_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x00C:
proto_tree_add_item(next_tree, hf_sdp_service_icon_url, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x00D:
protocol_order = 1;
list_offset = offset;
i_protocol = 1;
while (list_offset - offset < size) {
entry_offset = get_type_length(tvb, list_offset, &entry_length);
dissect_data_element(next_tree, &sub_tree, pinfo, tvb, list_offset);
entry_item = proto_tree_add_none_format(sub_tree, hf_profile_descriptor_list, tvb, entry_offset, entry_length, "Protocol Descriptor List #%u", i_protocol);
entry_tree = proto_item_add_subtree(entry_item, ett_btsdp_data_element);
list_offset = get_type_length(tvb, list_offset, &list_length);
wmem_strbuf_append(info_buf, "[");
dissect_protocol_descriptor_list(entry_tree, tvb,
pinfo, list_offset, list_length, info_buf,
service_info, &protocol_order);
list_offset += list_length;
wmem_strbuf_append(info_buf, "] ");
i_protocol += 1;
}
break;
case 0x100:
proto_tree_add_item(next_tree, hf_sdp_service_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x101:
proto_tree_add_item(next_tree, hf_sdp_service_description, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
case 0x102:
proto_tree_add_item(next_tree, hf_sdp_service_provider_name, tvb, offset, size, ENC_ASCII | ENC_NA);
new_str = tvb_get_string(wmem_packet_scope(), tvb, offset, size);
wmem_strbuf_append(info_buf, new_str);
break;
default:
found = FALSE;
}
}
if (!found) switch (type) {
case 0:
proto_tree_add_item(next_tree, hf_data_element_value_nil, tvb, offset, size, ENC_NA);
wmem_strbuf_append(info_buf, "Nil ");
break;
case 1: {
guint32 val = get_uint_by_size(tvb, offset, size_index);
proto_tree_add_item(next_tree, hf_data_element_value_unsigned_int, tvb, offset, size, ENC_BIG_ENDIAN);
wmem_strbuf_append_printf(info_buf, "%u ", val);
break;
}
case 2: {
guint32 val = get_int_by_size(tvb, offset, size_index);
proto_tree_add_item(next_tree, hf_data_element_value_signed_int, tvb, offset, size, ENC_BIG_ENDIAN);
wmem_strbuf_append_printf(info_buf, "%d ", val);
break;
}
case 3:
dissect_uuid(next_tree, tvb, offset, size, &uuid);
wmem_strbuf_append_printf(info_buf, ": %s", print_uuid(&uuid));
break;
case 8: /* fall through */
case 4: {
gchar *ptr = (gchar*)tvb_get_string(wmem_packet_scope(), tvb, offset, size);
proto_tree_add_item(next_tree, (type == 8) ? hf_data_element_value_url : hf_data_element_value_string, tvb, offset, size, ENC_NA | ENC_ASCII);
wmem_strbuf_append_printf(info_buf, "%s ", ptr);
break;
}
case 5: {
guint8 var = tvb_get_guint8(tvb, offset);
proto_tree_add_item(next_tree, hf_data_element_value_boolean, tvb, offset, size, ENC_BIG_ENDIAN);
wmem_strbuf_append_printf(info_buf, "%s ", var ? "true" : "false");
break;
}
case 6: /* Data Element sequence */
case 7: /* Data Element alternative */ {
proto_tree *st;
proto_item *ti;
gint bytes_to_go = size;
gint first = 1;
wmem_strbuf_t *substr;
ti = proto_tree_add_item(next_tree, (type == 6) ? hf_data_element_value_sequence : hf_data_element_value_alternative,
tvb, offset, size, ENC_NA);
st = proto_item_add_subtree(ti, ett_btsdp_des);
wmem_strbuf_append(info_buf, "{ ");
while (bytes_to_go > 0) {
if (!first) {
wmem_strbuf_append(info_buf, ", ");
} else {
first = 0;
}
size = dissect_sdp_type(st, pinfo, tvb, offset, attribute, service_uuid, service_did_vendor_id, service_did_vendor_id_source, service_info, &substr);
if (size < 1) {
break;
}
wmem_strbuf_append_printf(info_buf, "%s ", wmem_strbuf_get_str(substr));
offset += size ;
bytes_to_go -= size;
}
wmem_strbuf_append(info_buf, "} ");
break;
}
}
return new_offset - start_offset;
}
static gint
dissect_sdp_service_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset,
packet_info *pinfo, uuid_t uuid, gint service_offset,
service_info_t *service_info, gint number_of_attributes, gboolean attribute_only)
{
proto_tree *attribute_tree;
proto_item *attribute_item;
proto_tree *attribute_id_tree;
proto_item *attribute_id_item;
proto_tree *attribute_value_tree;
proto_item *attribute_value_item;
proto_tree *next_tree;
gint size = 0;
const gchar *attribute_name;
wmem_strbuf_t *attribute_value = NULL;
guint16 id;
gint service_did_vendor_id = 0;
gint service_did_vendor_id_source = 0;
gint hfx_attribute_id = hf_service_attribute_id_generic;
const value_string *name_vals = NULL;
const guint8 *profile_speficic = "";
gint new_offset;
gint old_offset;
guint8 type;
type = tvb_get_guint8(tvb, offset);
id = tvb_get_ntohs(tvb, offset + 1);
switch (uuid.bt_uuid) {
case BTSDP_DID_SERVICE_UUID:
name_vals = vs_did_attribute_id;
hfx_attribute_id = hf_service_attribute_id_did;
profile_speficic = "(DID) ";
service_did_vendor_id_source = findDidVendorIdSource(tvb, service_offset, number_of_attributes);
service_did_vendor_id = findDidVendorId(tvb, service_offset, number_of_attributes);
break;
case BTSDP_HID_SERVICE_UUID:
name_vals = vs_hid_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hid;
profile_speficic = "(HID) ";
break;
case BTSDP_SYNC_SERVICE_UUID:
name_vals = vs_synch_attribute_id;
hfx_attribute_id = hf_service_attribute_id_synch;
profile_speficic = "(SYNCH) ";
break;
case BTSDP_PBAP_PCE_SERVICE_UUID:
case BTSDP_PBAP_PSE_SERVICE_UUID:
case BTSDP_PBAP_SERVICE_UUID:
name_vals = vs_pbap_attribute_id;
hfx_attribute_id = hf_service_attribute_id_pbap;
profile_speficic = "(PBAP) ";
break;
case BTSDP_PAN_NAP_SERVICE_UUID:
name_vals = vs_pan_nap_attribute_id;
hfx_attribute_id = hf_service_attribute_id_pan_nap;
profile_speficic = "(PAN NAP) ";
break;
case BTSDP_PAN_GN_SERVICE_UUID:
name_vals = vs_pan_gn_attribute_id;
hfx_attribute_id = hf_service_attribute_id_pan_gn;
profile_speficic = "(PAN GN) ";
break;
case BTSDP_PAN_PANU_SERVICE_UUID:
name_vals = vs_pan_panu_attribute_id;
hfx_attribute_id = hf_service_attribute_id_pan_panu;
profile_speficic = "(PAN PANU) ";
break;
case BTSDP_OPP_SERVICE_UUID:
name_vals = vs_opp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_opp;
profile_speficic = "(OPP) ";
break;
case BTSDP_MAP_SERVICE_UUID:
case BTSDP_MAP_ACCESS_SRV_SERVICE_UUID:
name_vals = vs_map_mas_attribute_id;
hfx_attribute_id = hf_service_attribute_id_map_mas;
profile_speficic = "(MAP MAS) ";
break;
case BTSDP_WAP_SERVICE_UUID:
case BTSDP_WAP_CLIENT_SERVICE_UUID:
name_vals = vs_wap_attribute_id;
hfx_attribute_id = hf_service_attribute_id_wap;
profile_speficic = "(WAP) ";
break;
case BTSDP_HDP_SERVICE_UUID:
case BTSDP_HDP_SOURCE_SERVICE_UUID:
case BTSDP_HDP_SINK_SERVICE_UUID:
name_vals = vs_hdp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hdp;
profile_speficic = "(HDP) ";
break;
case BTSDP_HSP_SERVICE_UUID:
case BTSDP_HSP_HS_SERVICE_UUID:
name_vals = vs_hsp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hsp;
profile_speficic = "(HSP) ";
break;
case BTSDP_HCRP_SERVICE_UUID:
case BTSDP_HCRP_PRINT_SERVICE_UUID:
case BTSDP_HCRP_SCAN_SERVICE_UUID:
name_vals = vs_hcrp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hcrp;
profile_speficic = "(HCRP) ";
break;
case BTSDP_HFP_SERVICE_UUID:
name_vals = vs_hfp_gw_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hfp_hf;
profile_speficic = "(HFP HS) ";
break;
case BTSDP_HFP_GW_SERVICE_UUID:
name_vals = vs_hfp_ag_attribute_id;
hfx_attribute_id = hf_service_attribute_id_hfp_ag;
profile_speficic = "(HFP AG) ";
break;
case BTSDP_GNSS_UUID:
case BTSDP_GNSS_SERVER_UUID:
name_vals = vs_gnss_attribute_id;
hfx_attribute_id = hf_service_attribute_id_gnss;
profile_speficic = "(GNSS) ";
break;
case BTSDP_FTP_SERVICE_UUID:
name_vals = vs_ftp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_ftp;
profile_speficic = "(FTP) ";
break;
case BTSDP_FAX_SERVICE_UUID:
name_vals = vs_fax_attribute_id;
hfx_attribute_id = hf_service_attribute_id_fax;
profile_speficic = "(FAX) ";
break;
case BTSDP_CTP_SERVICE_UUID:
name_vals = vs_ctp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_ctp;
profile_speficic = "(CTP) ";
break;
case BTSDP_A2DP_SOURCE_SERVICE_UUID:
case BTSDP_A2DP_SINK_SERVICE_UUID:
case BTSDP_A2DP_DISTRIBUTION_SERVICE_UUID:
name_vals = vs_a2dp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_a2dp;
profile_speficic = "(A2DP) ";
break;
case BTSDP_AVRCP_TG_SERVICE_UUID:
case BTSDP_AVRCP_SERVICE_UUID:
case BTSDP_AVRCP_CT_SERVICE_UUID:
name_vals = vs_avrcp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_avrcp;
profile_speficic = "(AVRCP) ";
break;
case BTSDP_BIP_SERVICE_UUID:
case BTSDP_BIP_RESPONDER_SERVICE_UUID:
name_vals = vs_bip_imaging_responder_attribute_id;
hfx_attribute_id = hf_service_attribute_id_bip_imaging_responder;
profile_speficic = "(BIP IR) ";
break;
case BTSDP_BIP_AUTO_ARCH_SERVICE_UUID:
name_vals = vs_bip_imaging_other_attribute_id;
hfx_attribute_id = hf_service_attribute_id_bip_imaging_other;
profile_speficic = "(BIP IAA) ";
break;
case BTSDP_BIP_REF_OBJ_SERVICE_UUID:
name_vals = vs_bip_imaging_other_attribute_id;
hfx_attribute_id = hf_service_attribute_id_bip_imaging_other;
profile_speficic = "(BIP IRO) ";
break;
case BTSDP_BPP_SERVICE_UUID:
case BTSDP_BPP_STATUS_SERVICE_UUID:
case BTSDP_BPP_DIRECT_PRINTING_SERVICE_UUID:
case BTSDP_BPP_REFERENCE_PRINTING_SERVICE_UUID:
name_vals = vs_bpp_attribute_id;
hfx_attribute_id = hf_service_attribute_id_bpp;
profile_speficic = "(BPP) ";
break;
case BTSDP_BPP_REFLECTED_UI_SERVICE_UUID:
name_vals = vs_bpp_reflected_ui_attribute_id;
hfx_attribute_id = hf_service_attribute_id_bpp_rui;
profile_speficic = "(BPP RUI) ";
break;
case BTSDP_DUN_SERVICE_UUID:
name_vals = vs_dun_attribute_id;
hfx_attribute_id = hf_service_attribute_id_dun;
profile_speficic = "(DUN) ";
break;
}
if (name_vals && try_val_to_str(id, name_vals)) {
attribute_name = val_to_str(id, name_vals, "Unknown");
} else {
attribute_name = val_to_str(id, vs_general_attribute_id, "Unknown");
profile_speficic = "";
hfx_attribute_id = hf_service_attribute_id_generic;
}
if (!attribute_only) {
attribute_item = proto_tree_add_none_format(tree, hf_service_attribute, tvb, offset, -1,
"Service Attribute: %s%s (0x%x)", profile_speficic, attribute_name, id);
attribute_tree = proto_item_add_subtree(attribute_item, ett_btsdp_attribute);
} else {
attribute_tree = tree;
}
if (attribute_only && type == 0x0a) {
dissect_data_element(attribute_tree, &next_tree, pinfo, tvb, offset);
offset += 1;
attribute_id_item = proto_tree_add_item(next_tree, hf_attribute_id_range, tvb, offset, 4, ENC_BIG_ENDIAN);
attribute_id_tree = proto_item_add_subtree(attribute_id_item, ett_btsdp_attribute_id);
col_append_fstr(pinfo->cinfo, COL_INFO, "Attribute Range (0x%04x - 0x%04x) ",
tvb_get_ntohs(tvb, offset), tvb_get_ntohs(tvb, offset + 2));
proto_tree_add_item(attribute_id_tree, hf_attribute_id_range_from, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(attribute_id_tree, hf_attribute_id_range_to, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
} else {
attribute_id_item = proto_tree_add_none_format(attribute_tree, hf_service_attribute_id, tvb, offset, 3, "Attribute ID: %s", attribute_name);
attribute_id_tree = proto_item_add_subtree(attribute_id_item, ett_btsdp_attribute_id);
new_offset = dissect_data_element(attribute_id_tree, &next_tree, pinfo, tvb, offset);
proto_tree_add_item(next_tree, hfx_attribute_id, tvb, offset + 1, 2, ENC_BIG_ENDIAN);
offset = new_offset;
if (!attribute_only){
attribute_value_item = proto_tree_add_item(attribute_tree, hf_service_attribute_value, tvb, offset, -1, ENC_NA);
attribute_value_tree = proto_item_add_subtree(attribute_value_item, ett_btsdp_attribute_value);
dissect_sdp_type(attribute_value_tree, pinfo, tvb, offset, id, uuid,
service_did_vendor_id, service_did_vendor_id_source, service_info, &attribute_value);
old_offset = offset;
offset = get_type_length(tvb, offset, &size);
proto_item_append_text(attribute_item, ", value = %s", wmem_strbuf_get_str(attribute_value));
proto_item_set_len(attribute_item, 3 + size + (offset - old_offset));
proto_item_set_len(attribute_value_item, size + (offset - old_offset));
} else {
proto_item_append_text(attribute_id_item, " %s", profile_speficic);
col_append_fstr(pinfo->cinfo, COL_INFO, "[%s%s 0x%04x] ", profile_speficic, attribute_name, id);
}
}
return offset + size;
}
static gint
dissect_attribute_id_list(proto_tree *tree, tvbuff_t *tvb, gint offset,
packet_info *pinfo, uuid_t *uuid)
{
proto_item *list_item;
proto_tree *list_tree;
proto_tree *sub_tree;
gint start_offset;
gint previous_offset;
gint service_offset;
gint bytes_to_go;
uuid_t empty_uuid;
if (!uuid)
memset(&empty_uuid, 0, sizeof(uuid_t));
start_offset = offset;
list_item = proto_tree_add_item(tree, hf_attribute_id_list, tvb, offset, 0, ENC_NA);
list_tree = proto_item_add_subtree(list_item, ett_btsdp_attribute_idlist);
dissect_data_element(list_tree, &sub_tree, pinfo, tvb, offset);
offset = get_type_length(tvb, offset, &bytes_to_go);
service_offset = offset;
proto_item_set_len(list_item, offset - start_offset + bytes_to_go);
previous_offset = offset;
while (bytes_to_go > 0) {
offset = dissect_sdp_service_attribute(sub_tree, tvb, offset, pinfo, (uuid) ? *uuid : empty_uuid, service_offset, NULL, 1, TRUE);
bytes_to_go -= offset - previous_offset;
previous_offset = offset;
}
return offset - start_offset;
}
static gint
dissect_sdp_error_response(proto_tree *tree, tvbuff_t *tvb, gint offset)
{
proto_tree_add_item(tree, hf_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
return offset;
}
static gint
dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, gint offset,
packet_info *pinfo, uuid_t *service_uuid, btl2cap_data_t *l2cap_data)
{
proto_item *list_item;
proto_tree *list_tree;
proto_tree *next_tree;
gint start_offset = offset;
gint search_offset;
gint search_length;
gint len;
guint number_of_attributes;
guint16 attribute;
gint element_length;
gint new_offset;
gint service_offset;
uuid_t uuid;
wmem_tree_key_t key[10];
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_sdp_psm;
guint32 k_direction;
guint32 k_bd_addr_oui;
guint32 k_bd_addr_id;
guint32 k_service_type;
guint32 k_service_channel;
guint32 k_frame_number;
service_info_t *service_info;
wmem_array_t *uuid_array;
uuid_array = wmem_array_new(wmem_packet_scope(), sizeof(uuid_t));
offset = get_type_length(tvb, offset, &len);
memset(&uuid, 0, sizeof(uuid_t));
list_item = proto_tree_add_item(tree, hf_attribute_list, tvb,
start_offset, len + (offset - start_offset), ENC_NA);
list_tree = proto_item_add_subtree(list_item, ett_btsdp_attribute);
dissect_data_element(list_tree, &next_tree, pinfo, tvb, start_offset);
/* search for main service uuid */
search_offset = offset;
number_of_attributes = 0;
while ((search_offset - start_offset) < len) {
search_offset = get_type_length(tvb, search_offset, &search_length);
attribute = tvb_get_ntohs(tvb, search_offset);
search_offset += search_length;
search_offset = get_type_length(tvb, search_offset, &search_length);
if (attribute == 0x01) {
new_offset = 0;
while (new_offset <= search_offset) {
new_offset = get_type_length(tvb, search_offset, &element_length);
dissect_uuid(NULL, tvb, new_offset, element_length, &uuid);
wmem_array_append_one(uuid_array, uuid);
new_offset += element_length;
}
}
search_offset += search_length;
number_of_attributes += 1;
}
uuid = get_specified_uuid(uuid_array);
if (uuid.size == 0 && service_uuid)
uuid = *service_uuid;
if (!pinfo->fd->flags.visited) {
service_info = (service_info_t *) wmem_new(wmem_file_scope(), service_info_t);
service_info->interface_id = l2cap_data->interface_id;
service_info->adapter_id = l2cap_data->adapter_id;
service_info->sdp_psm = l2cap_data->psm;
service_info->direction = pinfo->p2p_dir;
if (service_info->direction == P2P_DIR_RECV) {
service_info->bd_addr_oui = l2cap_data->remote_bd_addr_oui;
service_info->bd_addr_id = l2cap_data->remote_bd_addr_id;
} else {
service_info->bd_addr_oui = 0;
service_info->bd_addr_id = 0;
}
service_info->uuid = uuid;
service_info->type = 0;
service_info->channel = 0;
service_info->protocol_order = 0;
service_info->protocol = -1;
service_info->parent_info = NULL;
} else {
service_info = NULL;
}
service_offset = offset;
while ((offset - start_offset) < len) {
offset = dissect_sdp_service_attribute(next_tree, tvb, offset, pinfo,
uuid, service_offset, service_info, number_of_attributes, FALSE);
}
if (!pinfo->fd->flags.visited) {
k_interface_id = l2cap_data->interface_id;
k_adapter_id = l2cap_data->adapter_id;
k_sdp_psm = l2cap_data->psm;
k_direction = service_info->direction;
k_bd_addr_oui = service_info->bd_addr_oui;
k_bd_addr_id = service_info->bd_addr_id;
k_service_type = service_info->type;
k_service_channel = service_info->channel;
k_frame_number = pinfo->fd->num;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_sdp_psm;
key[3].length = 1;
key[3].key = &k_direction;
key[4].length = 1;
key[4].key = &k_bd_addr_oui;
key[5].length = 1;
key[5].key = &k_bd_addr_id;
key[6].length = 1;
key[6].key = &k_service_type;
key[7].length = 1;
key[7].key = &k_service_channel;
key[8].length = 1;
key[8].key = &k_frame_number;
key[9].length = 0;
key[9].key = NULL;
wmem_tree_insert32_array(service_infos, key, service_info);
}
proto_item_set_len(list_item, offset - start_offset);
if (uuid.size)
proto_item_append_text(list_tree, " [count = %2u] (%s%s)",
number_of_attributes, (uuid.bt_uuid) ? "" : "CustomUUID: ", print_uuid(&uuid));
else
proto_item_append_text(list_tree, " [count = %2u]",
number_of_attributes);
return offset;
}
static gint
dissect_sdp_service_attribute_list_array(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, gint attribute_list_byte_count,
uuid_t *service_uuid, btl2cap_data_t *l2cap_data)
{
proto_item *lists_item;
proto_tree *lists_tree;
proto_tree *next_tree;
gint start_offset;
gint len;
guint number_of_attributes;
start_offset = offset;
offset = get_type_length(tvb, offset, &len);
lists_item = proto_tree_add_item(tree, hf_attribute_lists, tvb, start_offset,
attribute_list_byte_count, ENC_NA);
lists_tree = proto_item_add_subtree(lists_item, ett_btsdp_attribute);
dissect_data_element(lists_tree, &next_tree, pinfo, tvb, start_offset);
number_of_attributes = 0;
while (offset - start_offset < attribute_list_byte_count) {
number_of_attributes += 1;
offset = dissect_sdp_service_attribute_list(next_tree, tvb, offset,
pinfo, service_uuid, l2cap_data);
}
proto_item_append_text(lists_tree, " [count = %2u]", number_of_attributes);
return offset;
}
static gint
dissect_sdp_service_search_request(proto_tree *tree, tvbuff_t *tvb, gint offset,
packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
gint start_offset;
gint bytes_to_go;
gint size;
proto_item *ti;
proto_tree *st;
proto_tree *sub_tree = NULL;
uuid_t empty_uuid;
wmem_array_t *uuid_array = NULL;
start_offset = offset;
memset(&empty_uuid, 0, sizeof(uuid_t));
if (!pinfo->fd->flags.visited)
uuid_array = wmem_array_new(wmem_file_scope(), sizeof(uuid_t));
ti = proto_tree_add_item(tree, hf_service_search_pattern, tvb, offset, 0, ENC_NA);
st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern);
dissect_data_element(st, &sub_tree, pinfo, tvb, offset);
offset = get_type_length(tvb, offset, &bytes_to_go);
proto_item_set_len(ti, offset - start_offset + bytes_to_go);
while (bytes_to_go > 0) {
wmem_strbuf_t *str = NULL;
gint entry_offset;
gint entry_size;
uuid_t uuid;
size = dissect_sdp_type(sub_tree, pinfo, tvb, offset, -1, empty_uuid, 0, 0, NULL, &str);
entry_offset = get_type_length(tvb, offset, &entry_size);
dissect_uuid(NULL, tvb, entry_offset, entry_size, &uuid);
if (uuid_array)
wmem_array_append_one(uuid_array, uuid);
proto_item_append_text(ti, " %s", wmem_strbuf_get_str(str));
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", wmem_strbuf_get_str(str));
if (size < 1)
break;
offset += size;
bytes_to_go -= size;
}
proto_tree_add_item(tree, hf_maximum_service_record_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
reassemble_continuation_state(tvb, pinfo, offset, tid, TRUE,
0, 0, PDU_TYPE_SERVICE_SEARCH, NULL, NULL, NULL, &uuid_array, NULL, l2cap_data);
offset = dissect_continuation_state(tvb, tree, pinfo, offset);
return offset;
}
static gint
dissect_sdp_service_search_response(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
proto_tree *st;
proto_item *ti;
guint16 current_count;
gboolean is_first;
gboolean is_continued;
tvbuff_t *new_tvb;
guint i_record;
wmem_array_t *uuid_array = NULL;
wmem_array_t *record_handle_array = NULL;
proto_tree_add_item(tree, hf_ssr_total_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
current_count = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(tree, hf_ssr_current_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
ti = proto_tree_add_none_format(tree, hf_service_record_handle_list, tvb, offset,
current_count * 4, "Service Record Handle List [count = %u]", current_count);
st = proto_item_add_subtree(ti, ett_btsdp_ssr);
if (!pinfo->fd->flags.visited)
record_handle_array = wmem_array_new(wmem_packet_scope(), sizeof(guint32));
while (current_count > 0) {
proto_tree_add_item(st, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN);
if (record_handle_array) {
guint32 value;
value = tvb_get_ntohl(tvb, offset);
wmem_array_append_one(record_handle_array, value);
}
offset += 4;
current_count -= 1;
}
reassemble_continuation_state(tvb, pinfo, offset, tid, FALSE,
offset - current_count * 4, current_count * 4, PDU_TYPE_SERVICE_SEARCH,
&new_tvb, &is_first, &is_continued, &uuid_array, NULL, l2cap_data);
if (is_continued)
col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");
if (!pinfo->fd->flags.visited) {
record_handle_service_t *record_handle_service;
wmem_tree_key_t key[7];
guint32 k_interface_id;
guint32 k_adapter_id;
guint32 k_chandle;
guint32 k_psm;
guint32 k_record_handle;
guint32 k_frame_number;
guint32 interface_id;
guint32 adapter_id;
guint32 chandle;
guint32 psm;
guint32 record_handle;
guint32 frame_number;
interface_id = l2cap_data->interface_id;
adapter_id = l2cap_data->adapter_id;
chandle = l2cap_data->chandle;
psm = l2cap_data->psm;
frame_number = pinfo->fd->num;
k_interface_id = interface_id;
k_adapter_id = adapter_id;
k_chandle = chandle;
k_psm = psm;
k_frame_number = frame_number;
for (i_record = 0; i_record < wmem_array_get_count(record_handle_array); ++i_record) {
record_handle = *((guint32 *)wmem_array_index(record_handle_array, i_record));
k_record_handle = record_handle;
key[0].length = 1;
key[0].key = &k_interface_id;
key[1].length = 1;
key[1].key = &k_adapter_id;
key[2].length = 1;
key[2].key = &k_chandle;
key[3].length = 1;
key[3].key = &k_psm;
key[4].length = 1;
key[4].key = &k_record_handle;
key[5].length = 1;
key[5].key = &k_frame_number;
key[6].length = 0;
key[6].key = NULL;
record_handle_service = (record_handle_service_t *) wmem_new(wmem_file_scope(), record_handle_service_t);
record_handle_service->interface_id = interface_id;
record_handle_service->adapter_id = adapter_id;
record_handle_service->chandle = chandle;
record_handle_service->psm = psm;
record_handle_service->record_handle = record_handle;
record_handle_service->uuid_array = uuid_array;
wmem_tree_insert32_array(record_handle_services, key, record_handle_service);
}
}
offset = dissect_continuation_state(tvb, tree, pinfo, offset);
if (!is_first && new_tvb) {
proto_item *reassembled_item;
proto_tree *reassembled_tree;
gint new_offset = 0;
gint new_length;
new_length = tvb_length(new_tvb);
reassembled_item = proto_tree_add_item(tree, (is_continued) ? hf_partial_record_handle_list : hf_reassembled_record_handle_list,new_tvb, 0, new_length, ENC_NA);
proto_item_append_text(reassembled_item, " [count = %u]", new_length / 4);
reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
PROTO_ITEM_SET_GENERATED(reassembled_item);
while (new_length > 0) {
proto_tree_add_item(reassembled_tree, hf_sdp_service_record_handle, new_tvb,
new_offset, 4, ENC_BIG_ENDIAN);
new_offset += 4;
new_length -= 4;
}
}
return offset;
}
static gint
dissect_sdp_service_attribute_request(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
guint32 record_handle;
wmem_array_t *uuid_array;
uuid_t uuid;
proto_tree_add_item(tree, hf_sdp_service_record_handle, tvb, offset, 4, ENC_BIG_ENDIAN);
record_handle = tvb_get_ntohl(tvb, offset);
col_append_fstr(pinfo->cinfo, COL_INFO, ": 0x%08x - ", record_handle);
offset += 4;
proto_tree_add_item(tree, hf_maximum_attribute_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
uuid_array = get_uuids(pinfo, record_handle, l2cap_data);
uuid = get_specified_uuid(uuid_array);
offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid);
reassemble_continuation_state(tvb, pinfo, offset, tid, TRUE,
0, 0, PDU_TYPE_SERVICE_ATTRIBUTE, NULL, NULL, NULL, NULL, &record_handle, l2cap_data);
offset = dissect_continuation_state(tvb, tree, pinfo, offset);
return offset;
}
static gint
dissect_sdp_service_attribute_response(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
gint attribute_list_byte_count;
gboolean is_first;
gboolean is_continued;
tvbuff_t *new_tvb;
guint32 record_handle = 0;
uuid_t uuid;
proto_tree_add_item(tree, hf_attribute_list_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
attribute_list_byte_count = tvb_get_ntohs(tvb, offset);
offset += 2;
reassemble_continuation_state(tvb, pinfo,
offset + attribute_list_byte_count, tid, FALSE,
offset, attribute_list_byte_count,
PDU_TYPE_SERVICE_ATTRIBUTE, &new_tvb, &is_first,
&is_continued, NULL, &record_handle, l2cap_data);
if (!is_continued) {
wmem_array_t *uuid_array;
uuid_array = get_uuids(pinfo, record_handle, l2cap_data);
uuid = get_specified_uuid(uuid_array);
} else {
memset(&uuid, 0, sizeof(uuid_t));
}
if (is_first && !is_continued) {
dissect_sdp_service_attribute_list(tree, tvb, offset, pinfo, &uuid, l2cap_data);
} else {
proto_tree_add_item(tree, hf_fragment, tvb, offset,
attribute_list_byte_count, ENC_NA);
}
if (is_continued)
col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");
offset = dissect_continuation_state(tvb, tree, pinfo, offset + attribute_list_byte_count);
if (!is_first && new_tvb) {
proto_item *reassembled_item;
proto_tree *reassembled_tree;
add_new_data_source(pinfo, new_tvb, (is_continued) ? "Partial Reassembled SDP" : "Reassembled SDP");
reassembled_item = proto_tree_add_item(tree,
(is_continued) ? hf_partial_attribute_list : hf_reassembled_attribute_list,
new_tvb, 0, tvb_length(new_tvb), ENC_NA);
reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
PROTO_ITEM_SET_GENERATED(reassembled_item);
if (!is_continued) {
dissect_sdp_service_attribute_list(reassembled_tree, new_tvb, 0,
pinfo, &uuid, l2cap_data);
}
}
return offset;
}
static gint
dissect_sdp_service_search_attribute_request(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
proto_tree *ptree;
proto_item *pitem;
proto_tree *next_tree;
gint start_offset;
gint size;
gint bytes_to_go;
wmem_strbuf_t *info_buf = NULL;
uuid_t empty_uuid;
wmem_array_t *uuid_array = NULL;
uuid_t uuid;
memset(&empty_uuid, 0, sizeof(uuid_t));
if (!pinfo->fd->flags.visited)
uuid_array = wmem_array_new(wmem_file_scope(), sizeof(uuid_t));
else
uuid_array = wmem_array_new(wmem_packet_scope(), sizeof(uuid_t));
start_offset = offset;
pitem = proto_tree_add_item(tree, hf_service_search_pattern, tvb, offset, 0, ENC_NA);
ptree = proto_item_add_subtree(pitem, ett_btsdp_attribute);
dissect_data_element(ptree, &next_tree, pinfo, tvb, offset);
offset = get_type_length(tvb, offset, &bytes_to_go);
proto_item_set_len(pitem, bytes_to_go + (offset - start_offset));
while (bytes_to_go > 0) {
gint entry_offset;
gint entry_size;
uuid_t a_uuid;
memset(&a_uuid, 0, sizeof(uuid_t));
size = dissect_sdp_type(next_tree, pinfo, tvb, offset, -1, empty_uuid, 0, 0, NULL, &info_buf);
proto_item_append_text(pitem,"%s", wmem_strbuf_get_str(info_buf));
col_append_fstr(pinfo->cinfo, COL_INFO, "%s", wmem_strbuf_get_str(info_buf));
entry_offset = get_type_length(tvb, offset, &entry_size);
dissect_uuid(NULL, tvb, entry_offset, entry_size, &a_uuid);
if (uuid_array)
wmem_array_append_one(uuid_array, a_uuid);
offset += size;
bytes_to_go -= size;
}
col_append_fstr(pinfo->cinfo, COL_INFO, ": ");
proto_tree_add_item(tree, hf_maximum_attribute_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
uuid = get_specified_uuid(uuid_array);
offset += dissect_attribute_id_list(tree, tvb, offset, pinfo, &uuid);
reassemble_continuation_state(tvb, pinfo, offset, tid, TRUE,
0, 0, PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE, NULL, NULL, NULL, &uuid_array, NULL, l2cap_data);
offset = dissect_continuation_state(tvb, tree, pinfo, offset);
return offset;
}
static gint
dissect_sdp_service_search_attribute_response(proto_tree *tree, tvbuff_t *tvb,
gint offset, packet_info *pinfo, guint16 tid, btl2cap_data_t *l2cap_data)
{
gint attribute_list_byte_count;
gboolean is_first;
gboolean is_continued;
tvbuff_t *new_tvb;
uuid_t uuid;
wmem_array_t *uuid_array = NULL;
proto_tree_add_item(tree, hf_attribute_list_byte_count, tvb, offset, 2, ENC_BIG_ENDIAN);
attribute_list_byte_count = tvb_get_ntohs(tvb, offset);
offset += 2;
reassemble_continuation_state(tvb, pinfo,
offset + attribute_list_byte_count, tid, FALSE,
offset, attribute_list_byte_count,
PDU_TYPE_SERVICE_SEARCH_ATTRIBUTE, &new_tvb, &is_first,
&is_continued, &uuid_array, NULL, l2cap_data);
uuid = get_specified_uuid(uuid_array);
if (is_first && !is_continued) {
dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo,
attribute_list_byte_count, &uuid, l2cap_data);
} else {
proto_tree_add_item(tree, hf_fragment, tvb, offset,
attribute_list_byte_count, ENC_NA);
}
if (is_continued)
col_append_str(pinfo->cinfo, COL_INFO, "(fragment)");
offset = dissect_continuation_state(tvb, tree, pinfo, offset + attribute_list_byte_count);
if (!is_first && new_tvb) {
proto_item *reassembled_item;
proto_tree *reassembled_tree;
add_new_data_source(pinfo, new_tvb, (is_continued) ? "Partial Reassembled SDP" : "Reassembled SDP");
reassembled_item = proto_tree_add_item(tree,
(is_continued) ? hf_partial_attribute_list : hf_reassembled_attribute_list,
new_tvb, 0, tvb_length(new_tvb), ENC_NA);
reassembled_tree = proto_item_add_subtree(reassembled_item, ett_btsdp_reassembled);
PROTO_ITEM_SET_GENERATED(reassembled_item);
if (!is_continued)
dissect_sdp_service_attribute_list_array(reassembled_tree, new_tvb, 0,
pinfo, tvb_length(new_tvb), &uuid, l2cap_data);
}
return offset;
}
static gint
dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
proto_item *ti;
proto_tree *st;
gint offset = 0;
guint8 pdu_id;
guint16 tid;
btl2cap_data_t *l2cap_data;
/* Reject the packet if data is NULL */
if (data == NULL)
return 0;
l2cap_data = (btl2cap_data_t *) data;
ti = proto_tree_add_item(tree, proto_btsdp, tvb, 0, -1, ENC_NA);
st = proto_item_add_subtree(ti, ett_btsdp);
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP");
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 %d ",
pinfo->p2p_dir);
break;
}
proto_tree_add_item(st, hf_pdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
pdu_id = tvb_get_guint8(tvb, offset);
offset += 1;
col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
val_to_str_const(pdu_id, vs_pduid, "Unknown"));
proto_tree_add_item(st, hf_tid, tvb, offset, 2, ENC_BIG_ENDIAN);
tid = tvb_get_ntohs(tvb, offset);
offset += 2;
proto_tree_add_item(st, hf_parameter_length, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
switch (pdu_id) {
case 0x01:
offset = dissect_sdp_error_response(st, tvb, offset);
break;
case 0x02:
offset = dissect_sdp_service_search_request(st, tvb, offset, pinfo, tid, l2cap_data);
break;
case 0x03:
offset = dissect_sdp_service_search_response(st, tvb, offset, pinfo, tid, l2cap_data);
break;
case 0x04:
offset = dissect_sdp_service_attribute_request(st, tvb, offset, pinfo, tid, l2cap_data);
break;
case 0x05:
offset = dissect_sdp_service_attribute_response(st, tvb, offset, pinfo, tid, l2cap_data);
break;
case 0x06:
offset = dissect_sdp_service_search_attribute_request(st, tvb, offset, pinfo, tid, l2cap_data);
break;
case 0x07:
offset = dissect_sdp_service_search_attribute_response(st, tvb, offset, pinfo, tid, l2cap_data);
break;
}
return offset;
}
void
proto_register_btsdp(void)
{
module_t *module;
expert_module_t *expert_btsdp;
static hf_register_info hf[] = {
{ &hf_pdu_id,
{ "PDU", "btsdp.pdu",
FT_UINT8, BASE_HEX, VALS(vs_pduid), 0,
"PDU type", HFILL }
},
{ &hf_tid,
{ "Transaction Id", "btsdp.tid",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL}
},
{ &hf_parameter_length,
{ "Parameter Length", "btsdp.len",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL}
},
{ &hf_error_code,
{ "Error Code", "btsdp.error_code",
FT_UINT16, BASE_HEX, VALS(vs_error_code), 0,
NULL, HFILL}
},
{ &hf_ssr_total_count,
{ "Total Service Record Count", "btsdp.ssr.total_count",
FT_UINT16, BASE_DEC, NULL, 0,
"Total count of service records", HFILL}
},
{ &hf_ssr_current_count,
{ "Current Service Record Count", "btsdp.ssr.current_count",
FT_UINT16, BASE_DEC, NULL, 0,
"Count of service records in this message", HFILL}
},
{ &hf_attribute_id_list,
{ "Attribute ID List", "btsdp.attribute_id_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_id_range,
{ "Attribute Range", "btsdp.attribute_range",
FT_UINT32, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_id_range_from,
{ "Attribute Range From", "btsdp.attribute_range.from",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_id_range_to,
{ "Attribute Range To", "btsdp.attribute_range.to",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_list_byte_count,
{ "Attribute List Byte Count", "btsdp.attribute_list_byte_count",
FT_UINT16, BASE_DEC, NULL, 0,
"Count of bytes in attribute list response", HFILL}
},
{ &hf_maximum_service_record_count,
{"Maximum Service Record Count", "btsdp.maximum_service_record_count",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL}
},
{ &hf_maximum_attribute_byte_count,
{"Maximum Attribute Byte Count", "btsdp.maximum_attribute_byte_count",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL}
},
{ &hf_service_attribute,
{ "Service Attribute", "btsdp.service_attribute",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_service_attribute_id,
{ "Attribute", "btsdp.service_attribute.attribute",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_service_attribute_value,
{ "Value", "btsdp.service_attribute.value",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_profile_descriptor_list,
{ "Profile Descriptor List", "btsdp.profile_descriptor_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_list,
{ "Attribute List", "btsdp.attribute_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_attribute_lists,
{ "Attribute Lists", "btsdp.attribute_lists",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_service_search_pattern,
{ "Service Search Pattern", "btsdp.service_search_pattern",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_service_record_handle_list,
{ "Service Record Handle List", "btsdp.service_record_handle_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_continuation_state,
{ "Continuation State", "btsdp.continuation_state",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_continuation_state_length,
{ "Continuation State Length", "btsdp.continuation_state.length",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_continuation_state_value,
{ "Continuation State Value", "btsdp.continuation_state.value",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element,
{ "Data Element", "btsdp.data_element",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_type,
{ "Data Element Type", "btsdp.data_element.type",
FT_UINT8, BASE_DEC, VALS(vs_data_element_type), 0xF8,
NULL, HFILL }
},
{ &hf_data_element_size,
{ "Data Element Size", "btsdp.data_element.size",
FT_UINT8, BASE_DEC, VALS(vs_data_element_size), 0x07,
NULL, HFILL }
},
{ &hf_data_element_var_size,
{ "Data Element Var Size", "btsdp.data_element.var_size",
FT_UINT32, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value,
{ "Data Value", "btsdp.data_element.value",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_nil,
{ "Value: Nil", "btsdp.data_element.value.nil",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_signed_int,
{ "Value: Signed Int", "btsdp.data_element.value.signed_int",
FT_INT64, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_unsigned_int,
{ "Value: Unsigned Int", "btsdp.data_element.value.unsigned_int",
FT_UINT64, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_boolean,
{ "Value: Boolean", "btsdp.data_element.value.boolean",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_string,
{ "Value: String", "btsdp.data_element.value.string",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_url,
{ "Value: URL", "btsdp.data_element.value.url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_uuid_16,
{ "Value: UUID", "btsdp.data_element.value.uuid_16",
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bt_sig_uuid_vals_ext, 0,
NULL, HFILL }
},
{ &hf_data_element_value_uuid_32,
{ "Value: UUID", "btsdp.data_element.value.uuid_32",
FT_UINT32, BASE_HEX | BASE_EXT_STRING, &bt_sig_uuid_vals_ext, 0,
NULL, HFILL }
},
{ &hf_data_element_value_uuid_128,
{ "Value: UUID", "btsdp.data_element.value.uuid_128",
FT_BYTES, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_uuid,
{ "Value: Custom UUID", "btsdp.data_element.value.custom_uuid",
FT_BYTES, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_sequence,
{ "Value: Sequence", "btsdp.data_element.value.sequence",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_data_element_value_alternative,
{ "Value: Alternative", "btsdp.data_element.value.alternative",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_fragment,
{ "Data Fragment", "btsdp.fragment",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_partial_attribute_list,
{ "Partial Attribute List", "btsdp.partial_attribute_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_reassembled_attribute_list,
{ "Reassembled Attribute List", "btsdp.reassembled_attribute_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_partial_record_handle_list,
{ "Partial Record Handle List", "btsdp.partial_record_handle_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_reassembled_record_handle_list,
{ "Reassembled Record Handle List", "btsdp.reassembled_attribute_list",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_generic,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_general_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_a2dp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_a2dp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_avrcp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_avrcp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_bip_imaging_responder,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_bip_imaging_responder_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_bip_imaging_other,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_bip_imaging_other_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_bpp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_bpp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_bpp_rui,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_bpp_reflected_ui_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_ctp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_ctp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_did,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_did_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_dun,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_dun_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_fax,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_fax_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_ftp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_ftp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_gnss,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_gnss_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hfp_hf,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hfp_gw_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hfp_ag,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hfp_ag_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hcrp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hcrp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hsp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hsp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hdp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hdp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_hid,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_hid_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_wap,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_wap_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_map_mas,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_map_mas_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_opp,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_opp_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_pan_nap,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_pan_nap_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_pan_gn,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_pan_gn_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_pan_panu,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_pan_panu_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_pbap,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_pbap_attribute_id), 0,
NULL, HFILL }
},
{ &hf_service_attribute_id_synch,
{ "Attribute ID", "btsdp.service.attribute",
FT_UINT16, BASE_HEX, VALS(vs_synch_attribute_id), 0,
NULL, HFILL }
},
{ &hf_did_specification_id,
{ "Specification ID", "btsdp.service.did.specification_id",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_did_vendor_id,
{ "Vendor ID", "btsdp.service.did.vendor_id",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_did_vendor_id_bluetooth_sig,
{ "Vendor ID", "btsdp.service.did.vendor_id",
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &bthci_evt_comp_id_ext, 0,
NULL, HFILL }
},
{ &hf_did_vendor_id_usb_forum,
{ "Vendor ID", "btsdp.service.did.vendor_id",
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &ext_usb_vendors_vals, 0,
NULL, HFILL }
},
{ &hf_did_product_id,
{ "Product ID", "btsdp.service.did.product_id",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_did_primary_record,
{ "Primary Record", "btsdp.service.did.primary_record",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_did_version,
{ "Version", "btsdp.service.did.version",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_did_vendor_id_source,
{ "Vendor ID Source", "btsdp.service.did.vendor_id_source",
FT_UINT16, BASE_HEX, VALS(did_vendor_id_source_vals), 0,
NULL, HFILL }
},
{ &hf_a2dp_sink_supported_features_reserved,
{ "Supported Features: Reserved", "btsdp.service.a2dp.sink.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFFF0,
NULL, HFILL }
},
{ &hf_a2dp_sink_supported_features_amplifier,
{ "Supported Features: Amplifier", "btsdp.service.a2dp.sink.supported_features.amplifier",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_a2dp_sink_supported_features_recorder,
{ "Supported Features: Recorder", "btsdp.service.a2dp.sink.supported_features.recorder",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_a2dp_sink_supported_features_speaker,
{ "Supported Features: Speaker", "btsdp.service.a2dp.sink.supported_features.speaker",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_a2dp_sink_supported_features_headphone,
{ "Supported Features: Headphone", "btsdp.service.a2dp.sink.supported_features.headphone",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_a2dp_source_supported_features_reserved,
{ "Supported Features: Reserved", "btsdp.service.a2dp.source.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFFF0,
NULL, HFILL }
},
{ &hf_a2dp_source_supported_features_mixer,
{ "Supported Features: Mixer", "btsdp.service.a2dp.source.supported_features.mixer",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_a2dp_source_supported_features_tuner,
{ "Supported Features: Tuner", "btsdp.service.a2dp.source.supported_features.tuner",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_a2dp_source_supported_features_microphone,
{ "Supported Features: Microphone", "btsdp.service.a2dp.source.supported_features.microphone",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_a2dp_source_supported_features_player,
{ "Supported Features: Player", "btsdp.service.a2dp.source.supported_features.player",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_synch_supported_data_store,
{ "Supported Data Store", "btsdp.service.synch.supported_data_store",
FT_UINT8, BASE_HEX, VALS(synch_supported_data_store_vals), 0,
NULL, HFILL }
},
{ &hf_ctp_external_network,
{ "External Network", "btsdp.service.ctp.external_network",
FT_UINT8, BASE_HEX, VALS(ctp_external_network_vals), 0,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_reserved_7_15,
{ "Supported Features: Reserved", "btsdp.service.avrcp.ct.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFF80,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_browsing,
{ "Supported Features: Browsing", "btsdp.service.avrcp.ct.supported_features.browsing",
FT_BOOLEAN, 16, NULL, 0x0040,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_reserved_4_5,
{ "Supported Features: Reserved", "btsdp.service.avrcp.ct.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0x0030,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_category_4,
{ "Supported Features: Category 4: Menu", "btsdp.service.avrcp.ct.supported_features.category_4",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_category_3,
{ "Supported Features: Category 3: Tuner", "btsdp.service.avrcp.ct.supported_features.category_3",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_category_2,
{ "Supported Features: Category 2: Monitor/Amplifier", "btsdp.service.avrcp.ct.supported_features.category_2",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_avrcp_ct_supported_features_category_1,
{ "Supported Features: Category 1: Player/Recorder", "btsdp.service.avrcp.ct.supported_features.category_1",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_reserved_8_15,
{ "Supported Features: Reserved", "btsdp.service.avrcp.tg.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFF00,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_multiple_player,
{ "Supported Features: Multiple Player", "btsdp.service.avrcp.tg.supported_features.multiple_player",
FT_BOOLEAN, 16, NULL, 0x0080,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_browsing,
{ "Supported Features: Browsing", "btsdp.service.avrcp.tg.supported_features.browsing",
FT_BOOLEAN, 16, NULL, 0x0040,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_group_navigation,
{ "Supported Features: Group Navigation", "btsdp.service.avrcp.tg.supported_features.group_navigation",
FT_BOOLEAN, 16, NULL, 0x0020,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_settings,
{ "Supported Features: Settings", "btsdp.service.avrcp.tg.supported_features.settings",
FT_BOOLEAN, 16, NULL, 0x0010,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_category_4,
{ "Supported Features: Category 4: Menu", "btsdp.service.avrcp.tg.supported_features.category_4",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_category_3,
{ "Supported Features: Category 3: Tuner", "btsdp.service.avrcp.tg.supported_features.category_3",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_category_2,
{ "Supported Features: Category 2: Monitor/Amplifier", "btsdp.service.avrcp.tg.supported_features.category_2",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_avrcp_tg_supported_features_category_1,
{ "Supported Features: Category 1: Player/Recorder", "btsdp.service.avrcp.tg.supported_features.category_1",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_hsp_remote_audio_volume_control,
{ "Remote Audio Volume Control", "btsdp.service.hsp.remote_audio_volume_control",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_gnss_supported_features,
{ "Supported Features: Reserved", "btsdp.service.gnss.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFFFF,
NULL, HFILL }
},
{ &hf_pbap_pse_supported_repositories_reserved,
{ "Supported Repositories: Reserved", "btsdp.service.pbap.pse.supported_repositories.reserved",
FT_UINT8, BASE_HEX, NULL, 0xFC,
NULL, HFILL }
},
{ &hf_pbap_pse_supported_repositories_sim_card,
{ "Supported Repositories: SIM Card", "btsdp.service.pbap.pse.supported_repositories.sim_card",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
{ &hf_pbap_pse_supported_repositories_local_phonebook,
{ "Supported Repositories: Local Phonebook", "btsdp.service.pbap.pse.supported_repositories.local_phonebook",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
{ &hf_dun_support_audio_feedback,
{ "Support: Audio Feedback", "btsdp.dun.support.audio_feedback",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_dun_escape_sequence,
{ "Escape Sequence", "btsdp.dun.support.escape_sequence",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_fax_support_class_1,
{ "Support: Fax Class 1", "btsdp.fax.support.class_1",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_fax_support_class_2,
{ "Support: Fax Class 2.0", "btsdp.fax.support.class_2",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_fax_support_class_2_vendor,
{ "Support: Fax Class 2 Vendor", "btsdp.fax.support.class_2_vendor",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_fax_support_audio_feedback,
{ "Support: Audio Feedback", "btsdp.fax.support.audio_feedback",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_ftp_goep_l2cap_psm,
{ "GOEP L2CAP PSM", "btsdp.ftp.goep_l2cap_psm",
FT_UINT16, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_map_mas_instance_id,
{ "MAS Instance ID", "btsdp.map.mas.instance_id",
FT_UINT8, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_map_mas_supported_message_types_reserved,
{ "Supported Message Types: Reserved", "btsdp.map.mas.supported_message_types.reserved",
FT_UINT8, BASE_DEC_HEX, NULL, 0xF0,
NULL, HFILL }
},
{ &hf_map_mas_supported_message_types_mms,
{ "Supported Message Types: MMS", "btsdp.map.mas.supported_message_types.mms",
FT_BOOLEAN, 8, NULL, 0x08,
NULL, HFILL }
},
{ &hf_map_mas_supported_message_types_sms_cdma,
{ "Supported Message Types: SMS CDMA", "btsdp.map.mas.supported_message_types.sms_cdma",
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
{ &hf_map_mas_supported_message_types_sms_gsm,
{ "Supported Message Types: SMS GSM", "btsdp.map.mas.supported_message_types.sms_gsm",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
{ &hf_map_mas_supported_message_types_email,
{ "Supported Message Types: Email", "btsdp.map.mas.supported_message_types.email",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
{ &hf_hcrp_1284_id,
{ "1284 ID", "btsdp.hcrp.1284_id",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hcrp_device_location,
{ "Sevice Location", "btsdp.hcrp.device_location",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hcrp_device_name,
{ "Device Name", "btsdp.hcrp.device_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hcrp_friendly_name,
{ "Friendly Name", "btsdp.hcrp.friendly_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_wap_network_address,
{ "Network Address", "btsdp.wap.network_address",
FT_IPv4, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_wap_homepage_url,
{ "Homepage URL", "btsdp.wap.network_address",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_wap_gateway,
{ "Gateway", "btsdp.wap.gateway",
FT_UINT8, BASE_HEX, VALS(wap_gateway_vals), 0,
NULL, HFILL }
},
{ &hf_wap_stack_type,
{ "Stack Type", "btsdp.wap.stack_type",
FT_UINT8, BASE_HEX, VALS(wap_stack_type_vals), 0,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_reserved_5_7,
{ "Support: Reserved", "btsdp.hdp.support.reserved",
FT_UINT8, BASE_HEX, NULL, 0xE0,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_sync_master_role,
{ "Support: SyncMaster Role", "btsdp.hdp.support.sync_master_role",
FT_BOOLEAN, 8, NULL, 0x10,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_clock_synchronization_protocol,
{ "Support: Clock Synchronization Protocol", "btsdp.hdp.support.clock_synchronization_protocol",
FT_BOOLEAN, 8, NULL, 0x08,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_reconnect_acceptance,
{ "Support: Reconnect Acceptance", "btsdp.hdp.support.reconnect_acceptance",
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_reconnect_initiation,
{ "Support: Reconnect Initiation", "btsdp.hdp.support.reconnect_initiation",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
{ &hf_hdp_support_procedure_reserved,
{ "Support: Reserved", "btsdp.hdp.support.reserved",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
{ &hf_hdp_data_exchange,
{ "Data Exchange Specification", "btsdp.hdp.data_exchange_specification",
FT_UINT8, BASE_HEX, VALS(hdp_data_exchange_specification_vals), 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_data,
{ "Supported Features", "btsdp.hdp.supported_features_data",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_data_mdep_id,
{ "MDEP ID", "btsdp.hdp.supported_features_data.mdep_id",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_data_mdep_data_type,
{ "MDEP Data Type", "btsdp.hdp.supported_features_data.mdep_data_type",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_data_mdep_role,
{ "MDEP Role", "btsdp.hdp.supported_features_data.mdep_role",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_data_mdep_description,
{ "MDEP Description", "btsdp.hdp.supported_features_data.mdep_description",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_mdep_id,
{ "MDEP ID", "btsdp.hdp.supported_features.mdep_id",
FT_UINT8, BASE_DEC_HEX|BASE_RANGE_STRING, RVALS(hdp_mdep_id_rvals), 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_mdep_data_type,
{ "MDEP Data Type", "btsdp.hdp.supported_features.mdep_data_type",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_mdep_role,
{ "MDEP Role", "btsdp.hdp.supported_features.mdep_role",
FT_UINT8, BASE_HEX, VALS(hdp_mdep_role_vals), 0,
NULL, HFILL }
},
{ &hf_hdp_supported_features_mdep_description,
{ "MDEP Description", "btsdp.hdp.supported_features.mdep_description",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_pan_sercurity_description,
{ "Security Description", "btsdp.pan.security_description",
FT_UINT16, BASE_HEX, VALS(pan_security_description_vals), 0,
NULL, HFILL }
},
{ &hf_pan_ipv4_subnet,
{ "IPv4 Subnet", "btsdp.pan.ipv4_subnet",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_pan_ipv6_subnet,
{ "IPv6 Subnet", "btsdp.pan.ipv6_subnet",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_pan_net_access_type,
{ "Net Access Type", "btsdp.pan.net_access_type",
FT_UINT16, BASE_HEX, VALS(pan_net_access_type_vals), 0,
NULL, HFILL }
},
{ &hf_pan_max_net_access_rate,
{ "Max Net Access Rate", "btsdp.pan.max_net_access_rate",
FT_UINT32, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_opp_goep_l2cap_psm,
{ "GOEP L2CAP PSM", "btsdp.opp.goep_l2cap_psm",
FT_UINT16, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_opp_supported_format,
{ "Supported Format", "btsdp.opp.supported_format",
FT_UINT8, BASE_HEX, VALS(opp_supported_format_vals), 0,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_reserved,
{ "Supported Features: Reserved", "btsdp.service.hfp.hf.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFFC0,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_wide_band_speech,
{ "Supported Features: Wide Band Speech", "btsdp.service.hfp.hf.supported_features.wide_band_speech",
FT_BOOLEAN, 16, NULL, 0x0020,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_remote_volume_control,
{ "Supported Features: Remote Volume Control", "btsdp.service.hfp.hf.supported_features.remote_volume_control",
FT_BOOLEAN, 16, NULL, 0x0010,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_voice_recognition_activation,
{ "Supported Features: Voice Recognition Activation", "btsdp.service.hfp.hf.supported_features.voice_recognition_activation",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_cli_presentation_capability,
{ "Supported Features: CLI Presentation Capability", "btsdp.service.hfp.hf.supported_features.cli_presentation_capability",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_call_waiting_or_three_way_calling,
{ "Supported Features: Call Waiting or Three Way Calling", "btsdp.service.hfp.hf.supported_features.call_waiting_or_three_way_calling",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_hfp_hf_supported_features_ec_and_or_nr_function,
{ "Supported Features: EC and/or Nr Function", "btsdp.service.hfp.hf.supported_features.ec_and_or_nr_function",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_reserved,
{ "Supported Features: Reserved", "btsdp.service.hfp.gw.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFFC0,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_wide_band_speech,
{ "Supported Features: Wide Band Speech", "btsdp.service.hfp.gw.supported_features.wide_band_speech",
FT_BOOLEAN, 16, NULL, 0x0020,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_attach_phone_number_to_voice_tag,
{ "Supported Features: Attach a Phone Number to a Voice Tag", "btsdp.service.hfp.gw.supported_features.attach_a_phone_number_to_a_voice_tag",
FT_BOOLEAN, 16, NULL, 0x0010,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_inband_ring_tone_capability,
{ "Supported Features: Inband Ring Tone Capability", "btsdp.service.hfp.gw.supported_features.inband_ring_tone_capability",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_voice_recognition_function,
{ "Supported Features: Voice Recognition Function", "btsdp.service.hfp.gw.supported_features.voice_recognition_function",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_ec_and_or_nr_function,
{ "Supported Features: EC and/or Nr Function", "btsdp.service.hfp.gw.supported_features.ec_and_or_nr_function",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_hfp_gw_supported_features_three_way_calling,
{ "Supported Features: Three Way Calling", "btsdp.service.hfp.gw.supported_features.three_way_calling",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_hfp_gw_network,
{ "Network", "btsdp.service.hfp.gw.network",
FT_UINT8, BASE_HEX, VALS(hfp_gw_network_vals), 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_item,
{ "Protocol", "btsdp.protocol_item",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol,
{ "Protocol Entry", "btsdp.protocol",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_psm,
{ "L2CAP PSM", "btsdp.protocol.psm",
FT_UINT16, BASE_DEC_HEX | BASE_EXT_STRING, &ext_psm_vals, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_channel,
{ "RFCOMM Channel", "btsdp.protocol.channel",
FT_UINT8, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_gatt_handle_start,
{ "GATT Handle Start", "btsdp.protocol.gatt_handle_start",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_gatt_handle_end,
{ "GATT Handle Start", "btsdp.protocol.gatt_handle_end",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_version,
{ "Protocol Version", "btsdp.protocol.version",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_protocol_bnep_type,
{ "BNEP Type", "btsdp.protocol.bnep_type",
FT_UINT16, BASE_HEX, VALS(etype_vals), 0,
NULL, HFILL }
},
{ &hf_sdp_service_record_handle,
{ "Service Record Handle", "btsdp.service_record_handle",
FT_UINT32, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_record_state,
{ "Service Record State", "btsdp.service_record_state",
FT_UINT32, BASE_HEX_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_info_time_to_live,
{ "Service Info Time to Live", "btsdp.service_info_time_to_live",
FT_UINT32, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_availability,
{ "Service Availability", "btsdp.service_availability",
FT_UINT8, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_documentation_url,
{ "Documentation URL", "btsdp.documentation_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_client_executable_url,
{ "Service Client Executable URL", "btsdp.service_client_executable_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_icon_url,
{ "Icon URL", "btsdp.icon_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_name,
{ "Service Name", "btsdp.service_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_description,
{ "Service Description", "btsdp.service_description",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_service_provider_name,
{ "Provider Name", "btsdp.provider_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_lang,
{ "Language", "btsdp.lang",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_lang_code,
{ "Language Code", "btsdp.lang.code",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_sdp_lang_id,
{ "Language ID", "btsdp.lang.id",
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &usb_langid_vals_ext, 0,
NULL, HFILL }
},
{ &hf_sdp_lang_encoding,
{ "Language Encoding", "btsdp.lang.encoding",
FT_UINT16, BASE_HEX | BASE_EXT_STRING, &wap_mib_enum_vals_character_sets_ext, 0,
NULL, HFILL }
},
{ &hf_sdp_lang_attribute_base,
{ "Attribute Base", "btsdp.lang.attribute_base",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_device_release_number,
{ "Device Release Number", "btsdp.service.hid.device_release_number",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_parser_version,
{ "Parser Version", "btsdp.service.hid.parser_version",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_device_subclass_type,
{ "Device Subclass: Type", "btsdp.service.hid.device_subclass.type",
FT_UINT8, BASE_HEX, VALS(hid_device_subclass_type_vals), 0xC0,
NULL, HFILL }
},
{ &hf_hid_device_subclass_subtype,
{ "Device Subclass: SubType", "btsdp.service.hid.device_subclass.subtype",
FT_UINT8, BASE_HEX, VALS(hid_device_subclass_subtype_vals), 0x3C,
NULL, HFILL }
},
{ &hf_hid_device_subclass_reserved,
{ "Device Subclass: Reserved", "btsdp.service.hid.device_subclass.reserved",
FT_UINT8, BASE_HEX, NULL, 0x03,
NULL, HFILL }
},
{ &hf_hid_country_code,
{ "Country Code", "btsdp.service.hid.country_code",
FT_UINT8, BASE_DEC_HEX, VALS(hid_country_code_vals), 0,
NULL, HFILL }
},
{ &hf_hid_virtual_cable,
{ "Virtual Cable", "btsdp.service.hid.virtual_cable",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_reconnect_initiate,
{ "Reconnect Initiate", "btsdp.service.hid.reconnect_initiate",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_sdp_disable,
{ "SDP Disable", "btsdp.service.hid.sdp_disable",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_battery_power,
{ "Battery Power", "btsdp.service.hid.battery_power",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_remote_wake,
{ "Remote Wake", "btsdp.service.hid.remote_wake",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_normally_connectable,
{ "Normally Connectable", "btsdp.service.hid.normally_connectable",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_boot_device,
{ "Boot Device", "btsdp.service.hid.boot_device",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_profile_version,
{ "Profile Version", "btsdp.service.hid.profile_version",
FT_UINT16, BASE_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_supervision_timeout,
{ "Supervision Timeout", "btsdp.service.hid.supervision_timeout",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_ssr_host_max_latency,
{ "SSR Host Max Latency", "btsdp.service.hid.ssr_host_max_latency",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_ssr_host_min_timeout,
{ "SSR Host Min Timeout", "btsdp.service.hid.ssr_host_min_timeout",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_descriptor_list_type,
{ "Descriptor Type", "btsdp.service.hid.descriptor.type",
FT_UINT8, BASE_HEX, VALS(descriptor_list_type_vals), 0,
NULL, HFILL }
},
{ &hf_hid_lang,
{ "Language", "btsdp.service.hid.lang",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_descriptor_list_descriptor_data,
{ "Descriptor", "btsdp.service.hid.descriptor_list.descriptor_data",
FT_NONE, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_hid_descriptor_list_descriptor,
{ "Descriptor", "btsdp.service.hid.descriptor_list.descriptor",
FT_BYTES, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bip_supported_capabilities_reserved_4_7,
{ "Supported Capabilities: Reserved", "btsdp.service.bip.supported_capabilities.reserved",
FT_UINT8, BASE_HEX, NULL, 0xF0,
NULL, HFILL }
},
{ &hf_bip_supported_capabilities_displaying,
{ "Supported Capabilities: Displaying", "btsdp.service.bip.supported_capabilities.displaying",
FT_BOOLEAN, 8, NULL, 0x08,
NULL, HFILL }
},
{ &hf_bip_supported_capabilities_printing,
{ "Supported Capabilities: Printing", "btsdp.service.bip.supported_capabilities.printing",
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
{ &hf_bip_supported_capabilities_capturing,
{ "Supported Capabilities: Capturing", "btsdp.service.bip.supported_capabilities.capturing",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
{ &hf_bip_supported_capabilities_genering_imaging,
{ "Supported Capabilities: Genering Imaging", "btsdp.service.bip.supported_capabilities.genering_imaging",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
{ &hf_bip_supported_features_reserved_9_15,
{ "Supported Features: Reserved", "btsdp.service.bip.supported_features.reserved",
FT_UINT16, BASE_HEX, NULL, 0xFE00,
NULL, HFILL }
},
{ &hf_bip_supported_features_remote_display,
{ "Supported Features: Remote Display", "btsdp.service.bip.supported_features.remote_display",
FT_BOOLEAN, 16, NULL, 0x0100,
NULL, HFILL }
},
{ &hf_bip_supported_features_remote_camera,
{ "Supported Features: Remote Camera", "btsdp.service.bip.supported_features.remote_camera",
FT_BOOLEAN, 16, NULL, 0x0080,
NULL, HFILL }
},
{ &hf_bip_supported_features_automatic_archive,
{ "Supported Features: Automatic Archive", "btsdp.service.bip.supported_features.automatic_archive",
FT_BOOLEAN, 16, NULL, 0x0040,
NULL, HFILL }
},
{ &hf_bip_supported_features_advanced_image_printing,
{ "Supported Features: Advanced Image Printing","btsdp.service.bip.supported_features.advanced_image_printing",
FT_BOOLEAN, 16, NULL, 0x0020,
NULL, HFILL }
},
{ &hf_bip_supported_features_image_pull,
{ "Supported Features: Image Pull", "btsdp.service.bip.supported_features.image_pull",
FT_BOOLEAN, 16, NULL, 0x0010,
NULL, HFILL }
},
{ &hf_bip_supported_features_image_push_display,
{ "Supported Features: Image Push Display", "btsdp.service.bip.supported_features.image_push_display",
FT_BOOLEAN, 16, NULL, 0x0008,
NULL, HFILL }
},
{ &hf_bip_supported_features_image_push_print,
{ "Supported Features: Image Push Print", "btsdp.service.bip.supported_features.image_push_print",
FT_BOOLEAN, 16, NULL, 0x0004,
NULL, HFILL }
},
{ &hf_bip_supported_features_image_push_store,
{ "Supported Features: Image Push Store", "btsdp.service.bip.supported_features.image_push_store",
FT_BOOLEAN, 16, NULL, 0x0002,
NULL, HFILL }
},
{ &hf_bip_supported_features_image_push,
{ "Supported Features: Image Push", "btsdp.service.bip.supported_features.image_push",
FT_BOOLEAN, 16, NULL, 0x0001,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_17_31,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved",
FT_UINT32, BASE_HEX, NULL, 0xFFFE0000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_13_31,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved",
FT_UINT32, BASE_HEX, NULL, 0xFFFFE000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_11_31,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved",
FT_UINT32, BASE_HEX, NULL, 0xFFFFF800,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_1_11,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved",
FT_UINT32, BASE_HEX, NULL, 0x00000FFE,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_1_4,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved",
FT_UINT32, BASE_HEX, NULL, 0x0000001E,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_status,
{ "Supported Functions: Get Status", "btsdp.service.bip.supported_functions.get_status",
FT_BOOLEAN, 32, NULL, 0x00010000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_15,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved_15",
FT_BOOLEAN, 32, NULL, 0x00008000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_monitoring_image,
{ "Supported Functions: Get Monitoring Image", "btsdp.service.bip.supported_functions.get_monitoring_image",
FT_BOOLEAN, 32, NULL, 0x00004000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_start_archive,
{ "Supported Functions: Start Archive", "btsdp.service.bip.supported_functions.start_archive",
FT_BOOLEAN, 32, NULL, 0x00002000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_reserved_12,
{ "Supported Functions: Reserved", "btsdp.service.bip.supported_functions.reserved_12",
FT_BOOLEAN, 32, NULL, 0x00001000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_partial_image,
{ "Supported Functions: Get Partial Image", "btsdp.service.bip.supported_functions.get_partial_image",
FT_BOOLEAN, 32, NULL, 0x00001000,
NULL, HFILL }
},
{ &hf_bip_supported_functions_start_print,
{ "Supported Functions: Start Print", "btsdp.service.bip.supported_functions.start_print",
FT_BOOLEAN, 32, NULL, 0x00000800,
NULL, HFILL }
},
{ &hf_bip_supported_functions_delete_image,
{ "Supported Functions: Delete Image", "btsdp.service.bip.supported_functions.delete_image",
FT_BOOLEAN, 32, NULL, 0x00000400,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_linked_attachment,
{ "Supported Functions: Get Linked Attachment","btsdp.service.bip.supported_functions.get_linked_attachment",
FT_BOOLEAN, 32, NULL, 0x00000200,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_linked_thumbnail,
{ "Supported Functions: Get Linked Thumbnail", "btsdp.service.bip.supported_functions.get_linked_thumbnail",
FT_BOOLEAN, 32, NULL, 0x00000100,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_image,
{ "Supported Functions: Get Image", "btsdp.service.bip.supported_functions.get_image",
FT_BOOLEAN, 32, NULL, 0x00000080,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_image_property,
{ "Supported Functions: Get Image Property", "btsdp.service.bip.supported_functions.get_image_property",
FT_BOOLEAN, 32, NULL, 0x00000040,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_images_list,
{ "Supported Functions: Get Images List", "btsdp.service.bip.supported_functions.get_images_list",
FT_BOOLEAN, 32, NULL, 0x00000020,
NULL, HFILL }
},
{ &hf_bip_supported_functions_remote_display,
{ "Supported Functions: Remote Display", "btsdp.service.bip.supported_functions.remote_display",
FT_BOOLEAN, 32, NULL, 0x00000010,
NULL, HFILL }
},
{ &hf_bip_supported_functions_put_linked_thumbnail,
{ "Supported Functions: Put Linked Thumbnail", "btsdp.service.bip.supported_functions.put_linked_thumbnail",
FT_BOOLEAN, 32, NULL, 0x00000008,
NULL, HFILL }
},
{ &hf_bip_supported_functions_put_linked_attachment,
{ "Supported Functions: Put Linked Attachment","btsdp.service.bip.supported_functions.put_linked_attachment",
FT_BOOLEAN, 32, NULL, 0x00000004,
NULL, HFILL }
},
{ &hf_bip_supported_functions_put_image,
{ "Supported Functions: Put Image", "btsdp.service.bip.supported_functions.put_image",
FT_BOOLEAN, 32, NULL, 0x00000002,
NULL, HFILL }
},
{ &hf_bip_supported_functions_get_capabilities,
{ "Supported Functions: Get Capabilities", "btsdp.service.bip.supported_functions.get_capabilities",
FT_BOOLEAN, 32, NULL, 0x00000001,
NULL, HFILL }
},
{ &hf_bip_total_imaging_data_capacity,
{ "Total Imaging Data Capacity", "btsdp.bip.total_imaging_data_capacity",
FT_UINT64, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_bip_goep_l2cap_psm,
{ "GOEP L2CAP PSM", "btsdp.bip.goep_l2cap_psm",
FT_UINT16, BASE_DEC_HEX, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_document_formats_supported,
{ "Document Formats Supported", "btsdp.service.bpp.document_formats_supported",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_character_repertoires_support,
{ "Character Repertoires Support", "btsdp.service.bpp.character_repertoires_support",
FT_BYTES, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_xhtml_print_image_formats_supported,
{ "XHTML Print Image Formats Supported", "btsdp.service.bpp.xhtml_print_image_formats_supported",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_color_supported,
{ "Color Supported", "btsdp.service.bpp.color_supported",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_1284_id,
{ "1284 ID", "btsdp.service.bpp.1284_id",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_printer_name,
{ "Printer Name", "btsdp.service.bpp.printer_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_printer_location,
{ "Printer Location", "btsdp.service.bpp.location",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_duplex_supported,
{ "Duplex Supported", "btsdp.service.bpp.duplex_supported",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_media_types_supported,
{ "Media Types Supported", "btsdp.service.bpp.media_types_supported",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_max_media_width,
{ "Max Media Width", "btsdp.service.bpp.max_media_width",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_max_media_length,
{ "Max Media Length", "btsdp.service.bpp.max_media_length",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_enhanced_layout_supported,
{ "Enhanced Layout Supported", "btsdp.service.bpp.enhanced_layout_supported",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_rui_formats_supported,
{ "RUI Formats Supported", "btsdp.service.bpp.rui_formats_supported",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_reference_printing_rui_supported,
{ "Reference Printing RUI Supported","btsdp.service.bpp.reference_printing_rui_supported",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_direct_printing_rui_supported,
{ "Direct Printing RUI Supported", "btsdp.service.bpp.direct_printing_rui_supported",
FT_BOOLEAN, 8, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_reference_printing_top_url,
{ "Reference Printing Top URL", "btsdp.service.bpp.reference_printing_top_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_direct_printing_top_url,
{ "Direct Printing Top URL", "btsdp.service.bpp.direct_printing_top_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_device_name,
{ "Device Name", "btsdp.service.bpp.device_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
},
{ &hf_bpp_printer_admin_rui_top_url,
{ "Printer Admin RUI Top URL", "btsdp.service.bpp.printer_admin_rui_top_url",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }
}
};
static gint *ett[] = {
&ett_btsdp,
&ett_btsdp_ssr,
&ett_btsdp_des,
&ett_btsdp_attribute,
&ett_btsdp_attribute_id,
&ett_btsdp_attribute_value,
&ett_btsdp_service_search_pattern,
&ett_btsdp_attribute_idlist,
&ett_btsdp_continuation_state,
&ett_btsdp_data_element,
&ett_btsdp_data_element_value,
&ett_btsdp_reassembled,
&ett_btsdp_supported_features,
&ett_btsdp_supported_features_mdep_id,
&ett_btsdp_supported_features_mdep_data_type,
&ett_btsdp_supported_features_mdep_role,
&ett_btsdp_supported_features_mdep_description,
&ett_btsdp_protocol
};
static ei_register_info ei[] = {
{ &ei_btsdp_continuation_state_none, { "btsdp.expert.continuation_state_none", PI_MALFORMED, PI_WARN, "There is no Continuation State", EXPFILL }},
{ &ei_btsdp_continuation_state_large, { "btsdp.expert.continuation_state_large", PI_MALFORMED, PI_WARN, "Continuation State data is longer then 16", EXPFILL }},
{ &ei_data_element_value_large, { "btsdp.expert.data_element.value.large", PI_MALFORMED, PI_WARN, "Data size exceeds the length of payload", EXPFILL }},
};
proto_btsdp = proto_register_protocol("Bluetooth SDP Protocol", "BT SDP", "btsdp");
btsdp_handle = new_register_dissector("btsdp", dissect_btsdp, proto_btsdp);
proto_register_field_array(proto_btsdp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_btsdp = expert_register_protocol(proto_btsdp);
expert_register_field_array(expert_btsdp, ei, array_length(ei));
tid_requests = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
continuation_states = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
record_handle_services = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
service_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
module = prefs_register_protocol(proto_btsdp, NULL);
prefs_register_static_text_preference(module, "bnep.version",
"Bluetooth Protocol SDP version from Core 4.0",
"Version of protocol supported by this dissector.");
}
void
proto_reg_handoff_btsdp(void)
{
dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle);
dissector_add_handle("btl2cap.cid", btsdp_handle);
btrfcomm_service_table = find_dissector_table("btrfcomm.service");
btl2cap_service_table = find_dissector_table("btl2cap.service");
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/