summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-btle.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:53 +0000
commita86c5f7cae7ec9a3398300555a0b644689d946a1 (patch)
tree39fe4b107c71174fd1e8a8ceb9a4d2aa14116248 /epan/dissectors/packet-btle.c
parentReleasing progress-linux version 4.2.6-1~progress7.99u1. (diff)
downloadwireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.tar.xz
wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.zip
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-btle.c')
-rw-r--r--epan/dissectors/packet-btle.c5584
1 files changed, 2887 insertions, 2697 deletions
diff --git a/epan/dissectors/packet-btle.c b/epan/dissectors/packet-btle.c
index 00017448..29476de3 100644
--- a/epan/dissectors/packet-btle.c
+++ b/epan/dissectors/packet-btle.c
@@ -22,6 +22,8 @@
#include <epan/expert.h>
#include <epan/proto_data.h>
#include <epan/reassemble.h>
+#include <epan/tfs.h>
+#include <epan/unit_strings.h>
#include <wiretap/wtap.h>
@@ -29,339 +31,339 @@
#include "packet-bthci_cmd.h"
#include "packet-bthci_acl.h"
-static int proto_btle = -1;
-static int proto_btle_rf = -1;
-static int proto_nordic_ble = -1;
-
-static int hf_access_address = -1;
-static int hf_coding_indicator = -1;
-static int hf_crc = -1;
-static int hf_master_bd_addr = -1;
-static int hf_slave_bd_addr = -1;
-static int hf_length = -1;
-static int hf_advertising_header = -1;
-static int hf_advertising_header_pdu_type = -1;
-static int hf_advertising_header_ch_sel = -1;
-static int hf_advertising_header_rfu_1 = -1;
-static int hf_advertising_header_rfu_2 = -1;
-static int hf_advertising_header_rfu_3 = -1;
-static int hf_advertising_header_rfu_4 = -1;
-static int hf_advertising_header_randomized_tx = -1;
-static int hf_advertising_header_randomized_rx = -1;
-static int hf_advertising_header_length = -1;
-static int hf_advertising_address = -1;
-static int hf_initiator_addresss = -1;
-static int hf_target_addresss = -1;
-static int hf_scanning_address = -1;
-static int hf_scan_response_data = -1;
-static int hf_link_layer_data = -1;
-static int hf_link_layer_data_access_address = -1;
-static int hf_link_layer_data_crc_init = -1;
-static int hf_link_layer_data_window_size = -1;
-static int hf_link_layer_data_window_offset = -1;
-static int hf_link_layer_data_interval = -1;
-static int hf_link_layer_data_latency = -1;
-static int hf_link_layer_data_timeout = -1;
-static int hf_link_layer_data_channel_map = -1;
-static int hf_link_layer_data_hop = -1;
-static int hf_link_layer_data_sleep_clock_accuracy = -1;
-static int hf_extended_advertising_header = -1;
-static int hf_extended_advertising_header_length = -1;
-static int hf_extended_advertising_mode = -1;
-static int hf_extended_advertising_flags = -1;
-static int hf_extended_advertising_flags_adva = -1;
-static int hf_extended_advertising_flags_targeta = -1;
-static int hf_extended_advertising_flags_cte_info = -1;
-static int hf_extended_advertising_flags_advdatainfo = -1;
-static int hf_extended_advertising_flags_aux_ptr = -1;
-static int hf_extended_advertising_flags_sync_info = -1;
-static int hf_extended_advertising_flags_tx_power = -1;
-static int hf_extended_advertising_flags_reserved = -1;
-static int hf_extended_advertising_cte_info = -1;
-static int hf_extended_advertising_cte_info_time = -1;
-static int hf_extended_advertising_cte_info_rfu = -1;
-static int hf_extended_advertising_cte_info_type = -1;
-static int hf_extended_advertising_data_info = -1;
-static int hf_extended_advertising_data_info_did = -1;
-static int hf_extended_advertising_data_info_sid = -1;
-static int hf_extended_advertising_aux_ptr = -1;
-static int hf_extended_advertising_aux_ptr_channel = -1;
-static int hf_extended_advertising_aux_ptr_ca = -1;
-static int hf_extended_advertising_aux_ptr_offset_units = -1;
-static int hf_extended_advertising_aux_ptr_aux_offset = -1;
-static int hf_extended_advertising_aux_ptr_aux_phy = -1;
-static int hf_extended_advertising_sync_info = -1;
-static int hf_extended_advertising_sync_info_offset = -1;
-static int hf_extended_advertising_sync_info_offset_units = -1;
-static int hf_extended_advertising_sync_info_offset_adjust = -1;
-static int hf_extended_advertising_sync_info_reserved = -1;
-static int hf_extended_advertising_sync_info_interval = -1;
-static int hf_extended_advertising_sync_info_channel_map = -1;
-static int hf_extended_advertising_sync_info_sleep_clock_accuracy = -1;
-static int hf_extended_advertising_sync_info_access_address = -1;
-static int hf_extended_advertising_sync_info_crc_init = -1;
-static int hf_extended_advertising_sync_info_event_counter = -1;
-static int hf_extended_advertising_tx_power = -1;
-static int hf_extended_advertising_header_acad = -1;
-static int hf_extended_advertising_had_fragment = -1;
-static int hf_data_header = -1;
-static int hf_data_header_length = -1;
-static int hf_data_header_rfu = -1;
-static int hf_data_header_llid = -1;
-static int hf_data_header_llid_connectediso = -1;
-static int hf_data_header_llid_broadcastiso = -1;
-static int hf_data_header_more_data = -1;
-static int hf_data_header_cte_info_present = -1;
-static int hf_data_header_sequence_number = -1;
-static int hf_data_header_next_expected_sequence_number = -1;
-static int hf_data_header_rfu_57 = -1;
-static int hf_data_header_rfu_67 = -1;
-static int hf_data_header_close_isochronous_event = -1;
-static int hf_data_header_null_pdu_indicator = -1;
-static int hf_data_header_control_subevent_sequence_number = -1;
-static int hf_data_header_control_subevent_transmission_flag = -1;
-static int hf_data_header_cte_info = -1;
-static int hf_data_header_cte_info_time = -1;
-static int hf_data_header_cte_info_rfu = -1;
-static int hf_data_header_cte_info_type = -1;
-static int hf_control_opcode = -1;
-static int hf_l2cap_index = -1;
-static int hf_l2cap_fragment = -1;
-static int hf_connection_parameters_in = -1;
-static int hf_control_reject_opcode = -1;
-static int hf_control_error_code = -1;
-static int hf_control_unknown_type = -1;
-static int hf_control_version_number = -1;
-static int hf_control_company_id = -1;
-static int hf_control_subversion_number = -1;
-static int hf_control_feature_set = -1;
-static int hf_control_feature_set_le_encryption = -1;
-static int hf_control_feature_set_connection_parameters_request_procedure = -1;
-static int hf_control_feature_set_extended_reject_indication = -1;
-static int hf_control_feature_set_slave_initiated_features_exchange = -1;
-static int hf_control_feature_set_le_ping = -1;
-static int hf_control_feature_set_le_pkt_len_ext = -1;
-static int hf_control_feature_set_ll_privacy = -1;
-static int hf_control_feature_set_ext_scan_flt_pol = -1;
-static int hf_control_feature_set_le_2m_phy = -1;
-static int hf_control_feature_set_stable_modulation_index_transmitter = -1;
-static int hf_control_feature_set_stable_modulation_index_receiver = -1;
-static int hf_control_feature_set_le_coded_phy = -1;
-static int hf_control_feature_set_le_extended_advertising = -1;
-static int hf_control_feature_set_le_periodic_advertising = -1;
-static int hf_control_feature_set_channel_selection_algorithm_2 = -1;
-static int hf_control_feature_set_le_power_class_1 = -1;
-static int hf_control_feature_set_minimum_number_of_used_channels_procedure = -1;
-static int hf_control_feature_set_connection_cte_request = -1;
-static int hf_control_feature_set_connection_cte_response = -1;
-static int hf_control_feature_set_connectionless_cte_tx = -1;
-static int hf_control_feature_set_connectionless_cte_rx = -1;
-static int hf_control_feature_set_antenna_switching_tx_aod = -1;
-static int hf_control_feature_set_antenna_switching_rx_aoa = -1;
-static int hf_control_feature_set_cte_rx = -1;
-static int hf_control_feature_set_past_sender = -1;
-static int hf_control_feature_set_past_receiver = -1;
-static int hf_control_feature_set_sca_updates = -1;
-static int hf_control_feature_set_remote_public_key_validation = -1;
-static int hf_control_feature_set_cis_central = -1;
-static int hf_control_feature_set_cis_peripheral = -1;
-static int hf_control_feature_set_iso_broadcast = -1;
-static int hf_control_feature_set_synchronized_receiver = -1;
-static int hf_control_feature_set_connected_iso_host_support = -1;
-static int hf_control_feature_set_le_power_control_request1 = -1;
-static int hf_control_feature_set_le_power_control_request2 = -1;
-static int hf_control_feature_set_le_path_loss_monitoring = -1;
-static int hf_control_feature_set_le_periodic_adv_adi_support = -1;
-static int hf_control_feature_set_connection_subrating = -1;
-static int hf_control_feature_set_connection_subrating_host_support = -1;
-static int hf_control_feature_set_channel_classification = -1;
-static int hf_control_feature_set_adv_coding_selection = -1;
-static int hf_control_feature_set_adv_coding_selection_host_support = -1;
-static int hf_control_feature_set_periodic_adv_with_responses_advertiser = -1;
-static int hf_control_feature_set_periodic_adv_with_responses_scanner = -1;
-static int hf_control_feature_set_reserved_bits = -1;
-static int hf_control_feature_set_reserved = -1;
-static int hf_control_window_size = -1;
-static int hf_control_window_offset = -1;
-static int hf_control_interval = -1;
-static int hf_control_latency = -1;
-static int hf_control_timeout = -1;
-static int hf_control_instant = -1;
-static int hf_control_rfu_5 = -1;
-static int hf_control_interval_min = -1;
-static int hf_control_interval_max = -1;
-static int hf_control_preferred_periodicity = -1;
-static int hf_control_reference_connection_event_count = -1;
-static int hf_control_offset_0 = -1;
-static int hf_control_offset_1 = -1;
-static int hf_control_offset_2 = -1;
-static int hf_control_offset_3 = -1;
-static int hf_control_offset_4 = -1;
-static int hf_control_offset_5 = -1;
-static int hf_control_channel_map = -1;
-static int hf_control_random_number = -1;
-static int hf_control_encrypted_diversifier = -1;
-static int hf_control_master_session_key_diversifier = -1;
-static int hf_control_master_session_initialization_vector = -1;
-static int hf_control_slave_session_key_diversifier = -1;
-static int hf_control_slave_session_initialization_vector = -1;
-static int hf_control_max_rx_octets = -1;
-static int hf_control_max_rx_time = -1;
-static int hf_control_max_tx_octets = -1;
-static int hf_control_max_tx_time = -1;
-static int hf_control_phys_sender_le_1m_phy = -1;
-static int hf_control_phys_sender_le_2m_phy = -1;
-static int hf_control_phys_sender_le_coded_phy = -1;
-static int hf_control_phys_update_le_1m_phy = -1;
-static int hf_control_phys_update_le_2m_phy = -1;
-static int hf_control_phys_update_le_coded_phy = -1;
-static int hf_control_phys_reserved_bits = -1;
-static int hf_control_tx_phys = -1;
-static int hf_control_rx_phys = -1;
-static int hf_control_m_to_s_phy = -1;
-static int hf_control_m_to_s_phy_le_1m_phy = -1;
-static int hf_control_m_to_s_phy_le_2m_phy = -1;
-static int hf_control_m_to_s_phy_le_coded_phy = -1;
-static int hf_control_m_to_s_phy_reserved_bits = -1;
-static int hf_control_s_to_m_phy = -1;
-static int hf_control_s_to_m_phy_le_1m_phy = -1;
-static int hf_control_s_to_m_phy_le_2m_phy = -1;
-static int hf_control_s_to_m_phy_le_coded_phy = -1;
-static int hf_control_s_to_m_phy_reserved_bits = -1;
-static int hf_control_phys = -1;
-static int hf_control_phys_le_1m_phy = -1;
-static int hf_control_phys_le_2m_phy = -1;
-static int hf_control_phys_le_coded_phy = -1;
-static int hf_control_min_used_channels = -1;
-static int hf_control_cte_min_len_req = -1;
-static int hf_control_cte_rfu = -1;
-static int hf_control_cte_type_req = -1;
-static int hf_control_sync_id = -1;
-static int hf_control_sync_info_offset = -1;
-static int hf_control_sync_info_offset_units = -1;
-static int hf_control_sync_info_offset_adjust = -1;
-static int hf_control_sync_info_reserved = -1;
-static int hf_control_sync_info_interval = -1;
-static int hf_control_sync_info_channel_map = -1;
-static int hf_control_sync_info_sleep_clock_accuracy = -1;
-static int hf_control_sync_info_access_address = -1;
-static int hf_control_sync_info_crc_init = -1;
-static int hf_control_sync_info_event_counter = -1;
-static int hf_control_sync_conn_event_count = -1;
-static int hf_control_sync_last_pa_event_counter = -1;
-static int hf_control_sync_sid = -1;
-static int hf_control_sync_atype = -1;
-static int hf_control_sync_sleep_clock_accuracy = -1;
-static int hf_control_sync_sync_conn_event_counter = -1;
-static int hf_control_sleep_clock_accuracy = -1;
-static int hf_control_cig_id = -1;
-static int hf_control_cis_id = -1;
-static int hf_control_max_sdu_m_to_s = -1;
-static int hf_control_rfu_1 = -1;
-static int hf_control_framed = -1;
-static int hf_control_max_sdu_s_to_m = -1;
-static int hf_control_rfu_2 = -1;
-static int hf_control_sdu_interval_m_to_s = -1;
-static int hf_control_rfu_3 = -1;
-static int hf_control_sdu_interval_s_to_m = -1;
-static int hf_control_rfu_4 = -1;
-static int hf_control_max_pdu_m_to_s = -1;
-static int hf_control_max_pdu_s_to_m = -1;
-static int hf_control_num_sub_events = -1;
-static int hf_control_sub_interval = -1;
-static int hf_control_bn_m_to_s = -1;
-static int hf_control_bn_s_to_m = -1;
-static int hf_control_ft_m_to_s = -1;
-static int hf_control_ft_s_to_m = -1;
-static int hf_control_iso_interval = -1;
-static int hf_control_cis_offset_min = -1;
-static int hf_control_cis_offset_max = -1;
-static int hf_control_conn_event_count = -1;
-static int hf_control_access_address = -1;
-static int hf_control_cis_offset = -1;
-static int hf_control_cig_sync_delay = -1;
-static int hf_control_cis_sync_delay = -1;
-static int hf_control_pwr_phy = -1;
-static int hf_control_pwr_phy_le_1m_phy = -1;
-static int hf_control_pwr_phy_le_2m_phy = -1;
-static int hf_control_pwr_phy_le_coded_s8_phy = -1;
-static int hf_control_pwr_phy_le_coded_s2_phy = -1;
-static int hf_control_pwr_phy_reserved_bits = -1;
-static int hf_control_delta = -1;
-static int hf_control_txpwr = -1;
-static int hf_control_pwrflags = -1;
-static int hf_control_pwrflags_min = -1;
-static int hf_control_pwrflags_max = -1;
-static int hf_control_pwrflags_reserved_bits = -1;
-static int hf_control_acceptable_power_reduction = -1;
-static int hf_control_subrate_factor_min = -1;
-static int hf_control_subrate_factor_max = -1;
-static int hf_control_max_latency = -1;
-static int hf_control_continuation_number = -1;
-static int hf_control_subrate_factor = -1;
-static int hf_control_subrate_base_event = -1;
-static int hf_control_channel_reporting_enable = -1;
-static int hf_control_channel_reporting_min_spacing = -1;
-static int hf_control_channel_reporting_max_delay = -1;
-static int hf_control_channel_classification = -1;
-static int hf_control_sync_info_rsp_access_address = -1;
-static int hf_control_sync_info_num_subevents = -1;
-static int hf_control_sync_info_subevent_interval = -1;
-static int hf_control_sync_info_response_slot_delay = -1;
-static int hf_control_sync_info_response_slot_spacing = -1;
-static int hf_big_control_opcode = -1;
-static int hf_isochronous_data = -1;
-static int hf_btle_l2cap_msg_fragments = -1;
-static int hf_btle_l2cap_msg_fragment = -1;
-static int hf_btle_l2cap_msg_fragment_overlap = -1;
-static int hf_btle_l2cap_msg_fragment_overlap_conflicts = -1;
-static int hf_btle_l2cap_msg_fragment_multiple_tails = -1;
-static int hf_btle_l2cap_msg_fragment_too_long_fragment = -1;
-static int hf_btle_l2cap_msg_fragment_error = -1;
-static int hf_btle_l2cap_msg_fragment_count = -1;
-static int hf_btle_l2cap_msg_reassembled_in = -1;
-static int hf_btle_l2cap_msg_reassembled_length = -1;
-static int hf_btle_ea_host_advertising_data_fragments = -1;
-static int hf_btle_ea_host_advertising_data_fragment = -1;
-static int hf_btle_ea_host_advertising_data_fragment_overlap = -1;
-static int hf_btle_ea_host_advertising_data_fragment_overlap_conflicts = -1;
-static int hf_btle_ea_host_advertising_data_fragment_multiple_tails = -1;
-static int hf_btle_ea_host_advertising_data_fragment_too_long_fragment = -1;
-static int hf_btle_ea_host_advertising_data_fragment_error = -1;
-static int hf_btle_ea_host_advertising_data_fragment_count = -1;
-static int hf_btle_ea_host_advertising_data_reassembled_in = -1;
-static int hf_btle_ea_host_advertising_data_reassembled_length = -1;
-
-static int hf_request_in_frame = -1;
-static int hf_response_in_frame = -1;
-
-static gint ett_btle = -1;
-static gint ett_advertising_header = -1;
-static gint ett_link_layer_data = -1;
-static gint ett_data_header = -1;
-static gint ett_data_header_cte_info = -1;
-static gint ett_features = -1;
-static gint ett_tx_phys = -1;
-static gint ett_rx_phys = -1;
-static gint ett_m_to_s_phy = -1;
-static gint ett_s_to_m_phy = -1;
-static gint ett_phys = -1;
-static gint ett_pwr_phy = -1;
-static gint ett_cte = -1;
-static gint ett_channel_map = -1;
-static gint ett_scan_response_data = -1;
-static gint ett_pwrflags = -1;
-static gint ett_btle_l2cap_msg_fragment = -1;
-static gint ett_btle_l2cap_msg_fragments = -1;
-static gint ett_btle_ea_host_advertising_data_fragment = -1;
-static gint ett_btle_ea_host_advertising_data_fragments = -1;
-static gint ett_extended_advertising_header = -1;
-static gint ett_extended_advertising_flags = -1;
-static gint ett_extended_advertising_cte_info = -1;
-static gint ett_extended_advertising_data_info = -1;
-static gint ett_extended_advertising_aux_pointer = -1;
-static gint ett_extended_advertising_sync_info = -1;
-static gint ett_extended_advertising_acad = -1;
+static int proto_btle;
+static int proto_btle_rf;
+static int proto_nordic_ble;
+
+static int hf_access_address;
+static int hf_coding_indicator;
+static int hf_crc;
+static int hf_central_bd_addr;
+static int hf_peripheral_bd_addr;
+static int hf_length;
+static int hf_advertising_header;
+static int hf_advertising_header_pdu_type;
+static int hf_advertising_header_ch_sel;
+static int hf_advertising_header_rfu_1;
+static int hf_advertising_header_rfu_2;
+static int hf_advertising_header_rfu_3;
+static int hf_advertising_header_rfu_4;
+static int hf_advertising_header_randomized_tx;
+static int hf_advertising_header_randomized_rx;
+static int hf_advertising_header_length;
+static int hf_advertising_address;
+static int hf_initiator_addresss;
+static int hf_target_addresss;
+static int hf_scanning_address;
+static int hf_scan_response_data;
+static int hf_link_layer_data;
+static int hf_link_layer_data_access_address;
+static int hf_link_layer_data_crc_init;
+static int hf_link_layer_data_window_size;
+static int hf_link_layer_data_window_offset;
+static int hf_link_layer_data_interval;
+static int hf_link_layer_data_latency;
+static int hf_link_layer_data_timeout;
+static int hf_link_layer_data_channel_map;
+static int hf_link_layer_data_hop;
+static int hf_link_layer_data_sleep_clock_accuracy;
+static int hf_extended_advertising_header;
+static int hf_extended_advertising_header_length;
+static int hf_extended_advertising_mode;
+static int hf_extended_advertising_flags;
+static int hf_extended_advertising_flags_adva;
+static int hf_extended_advertising_flags_targeta;
+static int hf_extended_advertising_flags_cte_info;
+static int hf_extended_advertising_flags_advdatainfo;
+static int hf_extended_advertising_flags_aux_ptr;
+static int hf_extended_advertising_flags_sync_info;
+static int hf_extended_advertising_flags_tx_power;
+static int hf_extended_advertising_flags_reserved;
+static int hf_extended_advertising_cte_info;
+static int hf_extended_advertising_cte_info_time;
+static int hf_extended_advertising_cte_info_rfu;
+static int hf_extended_advertising_cte_info_type;
+static int hf_extended_advertising_data_info;
+static int hf_extended_advertising_data_info_did;
+static int hf_extended_advertising_data_info_sid;
+static int hf_extended_advertising_aux_ptr;
+static int hf_extended_advertising_aux_ptr_channel;
+static int hf_extended_advertising_aux_ptr_ca;
+static int hf_extended_advertising_aux_ptr_offset_units;
+static int hf_extended_advertising_aux_ptr_aux_offset;
+static int hf_extended_advertising_aux_ptr_aux_phy;
+static int hf_extended_advertising_sync_info;
+static int hf_extended_advertising_sync_info_offset;
+static int hf_extended_advertising_sync_info_offset_units;
+static int hf_extended_advertising_sync_info_offset_adjust;
+static int hf_extended_advertising_sync_info_reserved;
+static int hf_extended_advertising_sync_info_interval;
+static int hf_extended_advertising_sync_info_channel_map;
+static int hf_extended_advertising_sync_info_sleep_clock_accuracy;
+static int hf_extended_advertising_sync_info_access_address;
+static int hf_extended_advertising_sync_info_crc_init;
+static int hf_extended_advertising_sync_info_event_counter;
+static int hf_extended_advertising_tx_power;
+static int hf_extended_advertising_header_acad;
+static int hf_extended_advertising_had_fragment;
+static int hf_data_header;
+static int hf_data_header_length;
+static int hf_data_header_rfu;
+static int hf_data_header_llid;
+static int hf_data_header_llid_connectediso;
+static int hf_data_header_llid_broadcastiso;
+static int hf_data_header_more_data;
+static int hf_data_header_cte_info_present;
+static int hf_data_header_sequence_number;
+static int hf_data_header_next_expected_sequence_number;
+static int hf_data_header_rfu_57;
+static int hf_data_header_rfu_67;
+static int hf_data_header_close_isochronous_event;
+static int hf_data_header_null_pdu_indicator;
+static int hf_data_header_control_subevent_sequence_number;
+static int hf_data_header_control_subevent_transmission_flag;
+static int hf_data_header_cte_info;
+static int hf_data_header_cte_info_time;
+static int hf_data_header_cte_info_rfu;
+static int hf_data_header_cte_info_type;
+static int hf_control_opcode;
+static int hf_l2cap_index;
+static int hf_l2cap_fragment;
+static int hf_connection_parameters_in;
+static int hf_control_reject_opcode;
+static int hf_control_error_code;
+static int hf_control_unknown_type;
+static int hf_control_version_number;
+static int hf_control_company_id;
+static int hf_control_subversion_number;
+static int hf_control_feature_set;
+static int hf_control_feature_set_le_encryption;
+static int hf_control_feature_set_connection_parameters_request_procedure;
+static int hf_control_feature_set_extended_reject_indication;
+static int hf_control_feature_set_peripheral_initiated_features_exchange;
+static int hf_control_feature_set_le_ping;
+static int hf_control_feature_set_le_pkt_len_ext;
+static int hf_control_feature_set_ll_privacy;
+static int hf_control_feature_set_ext_scan_flt_pol;
+static int hf_control_feature_set_le_2m_phy;
+static int hf_control_feature_set_stable_modulation_index_transmitter;
+static int hf_control_feature_set_stable_modulation_index_receiver;
+static int hf_control_feature_set_le_coded_phy;
+static int hf_control_feature_set_le_extended_advertising;
+static int hf_control_feature_set_le_periodic_advertising;
+static int hf_control_feature_set_channel_selection_algorithm_2;
+static int hf_control_feature_set_le_power_class_1;
+static int hf_control_feature_set_minimum_number_of_used_channels_procedure;
+static int hf_control_feature_set_connection_cte_request;
+static int hf_control_feature_set_connection_cte_response;
+static int hf_control_feature_set_connectionless_cte_tx;
+static int hf_control_feature_set_connectionless_cte_rx;
+static int hf_control_feature_set_antenna_switching_tx_aod;
+static int hf_control_feature_set_antenna_switching_rx_aoa;
+static int hf_control_feature_set_cte_rx;
+static int hf_control_feature_set_past_sender;
+static int hf_control_feature_set_past_receiver;
+static int hf_control_feature_set_sca_updates;
+static int hf_control_feature_set_remote_public_key_validation;
+static int hf_control_feature_set_cis_central;
+static int hf_control_feature_set_cis_peripheral;
+static int hf_control_feature_set_iso_broadcast;
+static int hf_control_feature_set_synchronized_receiver;
+static int hf_control_feature_set_connected_iso_host_support;
+static int hf_control_feature_set_le_power_control_request1;
+static int hf_control_feature_set_le_power_control_request2;
+static int hf_control_feature_set_le_path_loss_monitoring;
+static int hf_control_feature_set_le_periodic_adv_adi_support;
+static int hf_control_feature_set_connection_subrating;
+static int hf_control_feature_set_connection_subrating_host_support;
+static int hf_control_feature_set_channel_classification;
+static int hf_control_feature_set_adv_coding_selection;
+static int hf_control_feature_set_adv_coding_selection_host_support;
+static int hf_control_feature_set_periodic_adv_with_responses_advertiser;
+static int hf_control_feature_set_periodic_adv_with_responses_scanner;
+static int hf_control_feature_set_reserved_bits;
+static int hf_control_feature_set_reserved;
+static int hf_control_window_size;
+static int hf_control_window_offset;
+static int hf_control_interval;
+static int hf_control_latency;
+static int hf_control_timeout;
+static int hf_control_instant;
+static int hf_control_rfu_5;
+static int hf_control_interval_min;
+static int hf_control_interval_max;
+static int hf_control_preferred_periodicity;
+static int hf_control_reference_connection_event_count;
+static int hf_control_offset_0;
+static int hf_control_offset_1;
+static int hf_control_offset_2;
+static int hf_control_offset_3;
+static int hf_control_offset_4;
+static int hf_control_offset_5;
+static int hf_control_channel_map;
+static int hf_control_random_number;
+static int hf_control_encrypted_diversifier;
+static int hf_control_central_session_key_diversifier;
+static int hf_control_central_session_initialization_vector;
+static int hf_control_peripheral_session_key_diversifier;
+static int hf_control_peripheral_session_initialization_vector;
+static int hf_control_max_rx_octets;
+static int hf_control_max_rx_time;
+static int hf_control_max_tx_octets;
+static int hf_control_max_tx_time;
+static int hf_control_phys_sender_le_1m_phy;
+static int hf_control_phys_sender_le_2m_phy;
+static int hf_control_phys_sender_le_coded_phy;
+static int hf_control_phys_update_le_1m_phy;
+static int hf_control_phys_update_le_2m_phy;
+static int hf_control_phys_update_le_coded_phy;
+static int hf_control_phys_reserved_bits;
+static int hf_control_tx_phys;
+static int hf_control_rx_phys;
+static int hf_control_c_to_p_phy;
+static int hf_control_c_to_p_phy_le_1m_phy;
+static int hf_control_c_to_p_phy_le_2m_phy;
+static int hf_control_c_to_p_phy_le_coded_phy;
+static int hf_control_c_to_p_phy_reserved_bits;
+static int hf_control_p_to_c_phy;
+static int hf_control_p_to_c_phy_le_1m_phy;
+static int hf_control_p_to_c_phy_le_2m_phy;
+static int hf_control_p_to_c_phy_le_coded_phy;
+static int hf_control_p_to_c_phy_reserved_bits;
+static int hf_control_phys;
+static int hf_control_phys_le_1m_phy;
+static int hf_control_phys_le_2m_phy;
+static int hf_control_phys_le_coded_phy;
+static int hf_control_min_used_channels;
+static int hf_control_cte_min_len_req;
+static int hf_control_cte_rfu;
+static int hf_control_cte_type_req;
+static int hf_control_sync_id;
+static int hf_control_sync_info_offset;
+static int hf_control_sync_info_offset_units;
+static int hf_control_sync_info_offset_adjust;
+static int hf_control_sync_info_reserved;
+static int hf_control_sync_info_interval;
+static int hf_control_sync_info_channel_map;
+static int hf_control_sync_info_sleep_clock_accuracy;
+static int hf_control_sync_info_access_address;
+static int hf_control_sync_info_crc_init;
+static int hf_control_sync_info_event_counter;
+static int hf_control_sync_conn_event_count;
+static int hf_control_sync_last_pa_event_counter;
+static int hf_control_sync_sid;
+static int hf_control_sync_atype;
+static int hf_control_sync_sleep_clock_accuracy;
+static int hf_control_sync_sync_conn_event_counter;
+static int hf_control_sleep_clock_accuracy;
+static int hf_control_cig_id;
+static int hf_control_cis_id;
+static int hf_control_max_sdu_c_to_p;
+static int hf_control_rfu_1;
+static int hf_control_framed;
+static int hf_control_max_sdu_p_to_c;
+static int hf_control_rfu_2;
+static int hf_control_sdu_interval_c_to_p;
+static int hf_control_rfu_3;
+static int hf_control_sdu_interval_p_to_c;
+static int hf_control_rfu_4;
+static int hf_control_max_pdu_c_to_p;
+static int hf_control_max_pdu_p_to_c;
+static int hf_control_num_sub_events;
+static int hf_control_sub_interval;
+static int hf_control_bn_c_to_p;
+static int hf_control_bn_p_to_c;
+static int hf_control_ft_c_to_p;
+static int hf_control_ft_p_to_c;
+static int hf_control_iso_interval;
+static int hf_control_cis_offset_min;
+static int hf_control_cis_offset_max;
+static int hf_control_conn_event_count;
+static int hf_control_access_address;
+static int hf_control_cis_offset;
+static int hf_control_cig_sync_delay;
+static int hf_control_cis_sync_delay;
+static int hf_control_pwr_phy;
+static int hf_control_pwr_phy_le_1m_phy;
+static int hf_control_pwr_phy_le_2m_phy;
+static int hf_control_pwr_phy_le_coded_s8_phy;
+static int hf_control_pwr_phy_le_coded_s2_phy;
+static int hf_control_pwr_phy_reserved_bits;
+static int hf_control_delta;
+static int hf_control_txpwr;
+static int hf_control_pwrflags;
+static int hf_control_pwrflags_min;
+static int hf_control_pwrflags_max;
+static int hf_control_pwrflags_reserved_bits;
+static int hf_control_acceptable_power_reduction;
+static int hf_control_subrate_factor_min;
+static int hf_control_subrate_factor_max;
+static int hf_control_max_latency;
+static int hf_control_continuation_number;
+static int hf_control_subrate_factor;
+static int hf_control_subrate_base_event;
+static int hf_control_channel_reporting_enable;
+static int hf_control_channel_reporting_min_spacing;
+static int hf_control_channel_reporting_max_delay;
+static int hf_control_channel_classification;
+static int hf_control_sync_info_rsp_access_address;
+static int hf_control_sync_info_num_subevents;
+static int hf_control_sync_info_subevent_interval;
+static int hf_control_sync_info_response_slot_delay;
+static int hf_control_sync_info_response_slot_spacing;
+static int hf_big_control_opcode;
+static int hf_isochronous_data;
+static int hf_btle_l2cap_msg_fragments;
+static int hf_btle_l2cap_msg_fragment;
+static int hf_btle_l2cap_msg_fragment_overlap;
+static int hf_btle_l2cap_msg_fragment_overlap_conflicts;
+static int hf_btle_l2cap_msg_fragment_multiple_tails;
+static int hf_btle_l2cap_msg_fragment_too_long_fragment;
+static int hf_btle_l2cap_msg_fragment_error;
+static int hf_btle_l2cap_msg_fragment_count;
+static int hf_btle_l2cap_msg_reassembled_in;
+static int hf_btle_l2cap_msg_reassembled_length;
+static int hf_btle_ea_host_advertising_data_fragments;
+static int hf_btle_ea_host_advertising_data_fragment;
+static int hf_btle_ea_host_advertising_data_fragment_overlap;
+static int hf_btle_ea_host_advertising_data_fragment_overlap_conflicts;
+static int hf_btle_ea_host_advertising_data_fragment_multiple_tails;
+static int hf_btle_ea_host_advertising_data_fragment_too_long_fragment;
+static int hf_btle_ea_host_advertising_data_fragment_error;
+static int hf_btle_ea_host_advertising_data_fragment_count;
+static int hf_btle_ea_host_advertising_data_reassembled_in;
+static int hf_btle_ea_host_advertising_data_reassembled_length;
+
+static int hf_request_in_frame;
+static int hf_response_in_frame;
+
+static int ett_btle;
+static int ett_advertising_header;
+static int ett_link_layer_data;
+static int ett_data_header;
+static int ett_data_header_cte_info;
+static int ett_features;
+static int ett_tx_phys;
+static int ett_rx_phys;
+static int ett_c_to_p_phy;
+static int ett_p_to_c_phy;
+static int ett_phys;
+static int ett_pwr_phy;
+static int ett_cte;
+static int ett_channel_map;
+static int ett_scan_response_data;
+static int ett_pwrflags;
+static int ett_btle_l2cap_msg_fragment;
+static int ett_btle_l2cap_msg_fragments;
+static int ett_btle_ea_host_advertising_data_fragment;
+static int ett_btle_ea_host_advertising_data_fragments;
+static int ett_extended_advertising_header;
+static int ett_extended_advertising_flags;
+static int ett_extended_advertising_cte_info;
+static int ett_extended_advertising_data_info;
+static int ett_extended_advertising_aux_pointer;
+static int ett_extended_advertising_sync_info;
+static int ett_extended_advertising_acad;
static int * const hfx_extended_advertising_flags[] = {
&hf_extended_advertising_flags_adva,
@@ -379,7 +381,7 @@ static int * const hfx_control_feature_set_1[] = {
&hf_control_feature_set_le_encryption,
&hf_control_feature_set_connection_parameters_request_procedure,
&hf_control_feature_set_extended_reject_indication,
- &hf_control_feature_set_slave_initiated_features_exchange,
+ &hf_control_feature_set_peripheral_initiated_features_exchange,
&hf_control_feature_set_le_ping,
&hf_control_feature_set_le_pkt_len_ext,
&hf_control_feature_set_ll_privacy,
@@ -460,19 +462,19 @@ static int * const hfx_control_phys_update[] = {
NULL
};
-static int * const hfx_control_m_to_s_phy[] = {
- &hf_control_m_to_s_phy_le_1m_phy,
- &hf_control_m_to_s_phy_le_2m_phy,
- &hf_control_m_to_s_phy_le_coded_phy,
- &hf_control_m_to_s_phy_reserved_bits,
+static int * const hfx_control_c_to_p_phy[] = {
+ &hf_control_c_to_p_phy_le_1m_phy,
+ &hf_control_c_to_p_phy_le_2m_phy,
+ &hf_control_c_to_p_phy_le_coded_phy,
+ &hf_control_c_to_p_phy_reserved_bits,
NULL
};
-static int * const hfx_control_s_to_m_phy[] = {
- &hf_control_s_to_m_phy_le_1m_phy,
- &hf_control_s_to_m_phy_le_2m_phy,
- &hf_control_s_to_m_phy_le_coded_phy,
- &hf_control_s_to_m_phy_reserved_bits,
+static int * const hfx_control_p_to_c_phy[] = {
+ &hf_control_p_to_c_phy_le_1m_phy,
+ &hf_control_p_to_c_phy_le_2m_phy,
+ &hf_control_p_to_c_phy_le_coded_phy,
+ &hf_control_p_to_c_phy_reserved_bits,
NULL
};
@@ -514,19 +516,19 @@ static int * const hfx_control_pwrflags[] = {
NULL
};
-static expert_field ei_unknown_data = EI_INIT;
-static expert_field ei_access_address_matched = EI_INIT;
-static expert_field ei_access_address_bit_errors = EI_INIT;
-static expert_field ei_access_address_illegal = EI_INIT;
-static expert_field ei_crc_cannot_be_determined = EI_INIT;
-static expert_field ei_crc_incorrect = EI_INIT;
-static expert_field ei_missing_fragment_start = EI_INIT;
-static expert_field ei_retransmit = EI_INIT;
-static expert_field ei_nack = EI_INIT;
-static expert_field ei_control_proc_overlapping = EI_INIT;
-static expert_field ei_control_proc_invalid_collision = EI_INIT;
-static expert_field ei_control_proc_wrong_seq = EI_INIT;
-static expert_field ei_control_proc_invalid_conflict_resolution = EI_INIT;
+static expert_field ei_unknown_data;
+static expert_field ei_access_address_matched;
+static expert_field ei_access_address_bit_errors;
+static expert_field ei_access_address_illegal;
+static expert_field ei_crc_cannot_be_determined;
+static expert_field ei_crc_incorrect;
+static expert_field ei_missing_fragment_start;
+static expert_field ei_retransmit;
+static expert_field ei_nack;
+static expert_field ei_control_proc_overlapping;
+static expert_field ei_control_proc_invalid_collision;
+static expert_field ei_control_proc_wrong_seq;
+static expert_field ei_control_proc_invalid_conflict_resolution;
static dissector_handle_t btle_handle;
static dissector_handle_t btcommon_ad_handle;
@@ -534,10 +536,11 @@ static dissector_handle_t btcommon_le_channel_map_handle;
static dissector_handle_t btl2cap_handle;
static wmem_tree_t *connection_info_tree;
+static wmem_tree_t *periodic_adv_info_tree;
static wmem_tree_t *broadcastiso_connection_info_tree;
static wmem_tree_t *connection_parameter_info_tree;
static wmem_tree_t *adi_to_first_frame_tree;
-static guint32 l2cap_index;
+static uint32_t l2cap_index;
/* Reassembly */
static reassembly_table btle_l2cap_msg_reassembly_table;
@@ -592,8 +595,8 @@ static const fragment_items btle_ea_host_advertising_data_frag_items = {
};
typedef struct _ae_had_info_t {
- guint fragment_counter;
- guint32 first_frame_num;
+ unsigned fragment_counter;
+ uint32_t first_frame_num;
address adv_addr;
} ae_had_info_t;
@@ -602,10 +605,10 @@ typedef struct _control_proc_info_t {
* The first entry corresponds to the request, the remaining frames are responses.
* The longest sequence is needed for the encryption start procedure,
* which consists of 5 frames. */
- guint frames[5];
+ unsigned frames[5];
/* Opcode of the first control procedure packet. */
- guint8 proc_opcode;
+ uint8_t proc_opcode;
/* The frame where the procedure completes. Set to 0 when not yet known.
* This is used to avoid adding another frame to the control procedure
@@ -614,69 +617,70 @@ typedef struct _control_proc_info_t {
* This frame number may be ignored in the case where an LL_UNKNOWN_RSP is
* received after a procedure involving only one packet, like the
* LL_MIN_USED_CHANNELS_IND. */
- guint last_frame;
+ unsigned last_frame;
/* The frame number of the packet containing the instant value.
* If set to 0, there is no such frame.
*
* We need to store this frame number, as any event counter is
* a valid instant. */
- guint frame_with_instant_value;
+ unsigned frame_with_instant_value;
/* The event counter corresponding to the instant of the control procedure. */
- guint16 instant;
+ uint16_t instant;
} control_proc_info_t;
/* Store information about a connection direction */
typedef struct _direction_info_t {
- guint prev_seq_num : 1; /* Previous sequence number for this direction */
- guint segmentation_started : 1; /* 0 = No, 1 = Yes */
- guint segment_len_rem; /* The remaining segment length, used to find last segment */
- guint32 l2cap_index; /* Unique identifier for each L2CAP message */
+ unsigned prev_seq_num : 1; /* Previous sequence number for this direction */
+ unsigned segmentation_started : 1; /* 0 = No, 1 = Yes */
+ unsigned segment_len_rem; /* The remaining segment length, used to find last segment */
+ uint32_t l2cap_index; /* Unique identifier for each L2CAP message */
wmem_tree_t *control_procs; /* Control procedures initiated from this direction. */
} direction_info_t;
typedef struct _connection_parameter_info_t {
- guint32 parameters_frame;
+ uint32_t parameters_frame;
} connection_parameter_info_t;
/* Store information about a connection */
typedef struct _connection_info_t {
/* Address information */
- guint32 interface_id;
- guint32 adapter_id;
- guint32 access_address;
+ uint32_t interface_id;
+ uint32_t adapter_id;
+ uint32_t access_address;
+ uint32_t crc_init;
- guint8 master_bd_addr[6];
- guint8 slave_bd_addr[6];
+ uint8_t central_bd_addr[6];
+ uint8_t peripheral_bd_addr[6];
- guint16 connection_parameter_update_instant;
+ uint16_t connection_parameter_update_instant;
connection_parameter_info_t *connection_parameter_update_info;
/* Connection information */
/* Data used on the first pass to get info from previous frame, result will be in per_packet_data */
- guint first_data_frame_seen : 1;
- direction_info_t direction_info[3]; /* UNKNOWN, MASTER_SLAVE and SLAVE_MASTER */
+ unsigned first_data_frame_seen : 1;
+ direction_info_t direction_info[3]; /* UNKNOWN, CENTRAL_PERIPHERAL and PERIPHERAL_CENTRAL */
} connection_info_t;
/* Store information about a broadcast isochronous connection */
typedef struct _broadcastiso_connection_info_t {
/* Address information */
- guint32 interface_id;
- guint32 adapter_id;
- guint32 access_address;
+ uint32_t interface_id;
+ uint32_t adapter_id;
+ uint32_t access_address;
- guint8 master_bd_addr[6];
+ uint8_t central_bd_addr[6];
} broadcastiso_connection_info_t;
/* */
typedef struct _btle_frame_info_t {
- guint retransmit : 1; /* 0 = No, 1 = Retransmitted frame */
- guint ack : 1; /* 0 = Nack, 1 = Ack */
- guint more_fragments : 1; /* 0 = Last fragment, 1 = More fragments */
- guint missing_start : 1; /* 0 = No, 1 = Missing fragment start */
- guint32 l2cap_index; /* Unique identifier for each L2CAP message */
+ unsigned retransmit : 1; /* 0 = No, 1 = Retransmitted frame */
+ unsigned ack : 1; /* 0 = Nack, 1 = Ack */
+ unsigned more_fragments : 1; /* 0 = Last fragment, 1 = More fragments */
+ unsigned missing_start : 1; /* 0 = No, 1 = Missing fragment start */
+ uint32_t l2cap_index; /* Unique identifier for each L2CAP message */
} btle_frame_info_t;
static const value_string pdu_type_vals[] = {
@@ -774,7 +778,7 @@ typedef enum
LL_CTRL_OPCODE_PAUSE_ENC_RSP = 0x0B,
LL_CTRL_OPCODE_VERSION_IND = 0x0C,
LL_CTRL_OPCODE_REJECT_IND = 0x0D,
- LL_CTRL_OPCODE_SLAVE_FEATURE_REQ = 0x0E,
+ LL_CTRL_OPCODE_PERIPHERAL_FEATURE_REQ = 0x0E,
LL_CTRL_OPCODE_CONNECTION_PARAM_REQ = 0x0F,
LL_CTRL_OPCODE_CONNECTION_PARAM_RSP = 0x10,
LL_CTRL_OPCODE_REJECT_EXT_IND = 0x11,
@@ -820,7 +824,7 @@ static const value_string control_opcode_vals[] = {
{ LL_CTRL_OPCODE_PAUSE_ENC_RSP, "LL_PAUSE_ENC_RSP" },
{ LL_CTRL_OPCODE_VERSION_IND, "LL_VERSION_IND" },
{ LL_CTRL_OPCODE_REJECT_IND, "LL_REJECT_IND" },
- { LL_CTRL_OPCODE_SLAVE_FEATURE_REQ, "LL_SLAVE_FEATURE_REQ" },
+ { LL_CTRL_OPCODE_PERIPHERAL_FEATURE_REQ, "LL_PERIPHERAL_FEATURE_REQ" },
{ LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, "LL_CONNECTION_PARAM_REQ" },
{ LL_CTRL_OPCODE_CONNECTION_PARAM_RSP, "LL_CONNECTION_PARAM_RSP" },
{ LL_CTRL_OPCODE_REJECT_EXT_IND, "LL_REJECT_EXT_IND" },
@@ -932,7 +936,7 @@ static const true_false_string tfs_random_public = {
void proto_register_btle(void);
void proto_reg_handoff_btle(void);
-static gboolean btle_detect_retransmit = TRUE;
+static bool btle_detect_retransmit = true;
static void
btle_init(void)
@@ -950,10 +954,10 @@ btle_init(void)
* This implementation operates on nibbles and is therefore
* endian-neutral.
*/
-static guint32
-btle_crc(tvbuff_t *tvb, const guint8 payload_len, const guint32 crc_init)
+static uint32_t
+btle_crc(tvbuff_t *tvb, const uint8_t payload_len, const uint32_t crc_init)
{
- static const guint16 btle_crc_next_state_flips[256] = {
+ static const uint16_t btle_crc_next_state_flips[256] = {
0x0000, 0x32d8, 0x196c, 0x2bb4, 0x0cb6, 0x3e6e, 0x15da, 0x2702,
0x065b, 0x3483, 0x1f37, 0x2def, 0x0aed, 0x3835, 0x1381, 0x2159,
0x065b, 0x3483, 0x1f37, 0x2def, 0x0aed, 0x3835, 0x1381, 0x2159,
@@ -987,13 +991,13 @@ btle_crc(tvbuff_t *tvb, const guint8 payload_len, const guint32 crc_init)
0x2159, 0x1381, 0x3835, 0x0aed, 0x2def, 0x1f37, 0x3483, 0x065b,
0x2702, 0x15da, 0x3e6e, 0x0cb6, 0x2bb4, 0x196c, 0x32d8, 0x0000
};
- gint offset = 4; /* skip AA, CRC applies over PDU */
- guint32 state = crc_init;
- guint8 bytes_to_go = 2+payload_len; /* PDU includes header and payload */
+ int offset = 4; /* skip AA, CRC applies over PDU */
+ uint32_t state = crc_init;
+ uint8_t bytes_to_go = 2+payload_len; /* PDU includes header and payload */
while( bytes_to_go-- ) {
- guint8 byte = tvb_get_guint8(tvb, offset++);
- guint8 nibble = (byte & 0xf);
- guint8 byte_index = ((state >> 16) & 0xf0) | nibble;
+ uint8_t byte = tvb_get_uint8(tvb, offset++);
+ uint8_t nibble = (byte & 0xf);
+ uint8_t byte_index = ((state >> 16) & 0xf0) | nibble;
state = ((state << 4) ^ btle_crc_next_state_flips[byte_index]) & 0xffffff;
nibble = ((byte >> 4) & 0xf);
byte_index = ((state >> 16) & 0xf0) | nibble;
@@ -1002,9 +1006,11 @@ btle_crc(tvbuff_t *tvb, const guint8 payload_len, const guint32 crc_init)
return state;
}
-static const gchar * adv_pdu_type_str_get(const btle_context_t *btle_context, guint32 pdu_type)
+static const char * adv_pdu_type_str_get(const btle_context_t *btle_context, uint32_t pdu_type, bool is_periodic_adv)
{
- if (!btle_context || !(btle_context->channel < 37)) {
+ if (is_periodic_adv) {
+ return "AUX_SYNC_IND";
+ } else if (!btle_context || !(btle_context->channel < 37)) {
return val_to_str_ext_const(pdu_type, &pdu_type_vals_ext, "Unknown");
} else if (pdu_type == 0x07 && btle_context->aux_pdu_type_valid) {
return val_to_str_ext_const(btle_context->aux_pdu_type, &aux_pdu_common_vals_ext, "Unknown");
@@ -1020,26 +1026,26 @@ static const gchar * adv_pdu_type_str_get(const btle_context_t *btle_context, gu
* to the rest of the BTLE packet. See BT spec, Vol 6, Part B,
* Section 1.2.
*/
-static guint32
-reverse_bits_per_byte(const guint32 val)
+static uint32_t
+reverse_bits_per_byte(const uint32_t val)
{
- const guint8 nibble_rev[16] = {
+ static const uint8_t nibble_rev[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
};
- guint32 retval = 0;
+ uint32_t retval = 0;
unsigned byte_index;
for (byte_index=0; byte_index<4; byte_index++) {
- guint shiftA = byte_index*8;
- guint shiftB = shiftA+4;
+ unsigned shiftA = byte_index*8;
+ unsigned shiftB = shiftA+4;
retval |= (nibble_rev[((val >> shiftA) & 0xf)] << shiftB);
retval |= (nibble_rev[((val >> shiftB) & 0xf)] << shiftA);
}
return retval;
}
-static gint
-dissect_feature_set(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_feature_set(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_item *sub_item;
proto_tree *sub_tree;
@@ -1071,8 +1077,8 @@ dissect_feature_set(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_conn_param_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_conn_param_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_interval_min, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
@@ -1113,8 +1119,8 @@ dissect_conn_param_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_length_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_length_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_max_rx_octets, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
@@ -1131,8 +1137,8 @@ dissect_length_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_phy_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_phy_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_tx_phys, ett_tx_phys, hfx_control_phys_sender, ENC_NA);
offset += 1;
@@ -1143,13 +1149,13 @@ dissect_phy_req_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_periodic_sync_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset, packet_info *pinfo, guint32 interface_id, guint32 adapter_id)
+static int
+dissect_periodic_sync_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset, packet_info *pinfo, uint32_t interface_id, uint32_t adapter_id)
{
- guint32 sync_offset, interval;
- gint reserved_offset;
- guint16 sf;
- guint8 bd_addr[6];
+ uint32_t sync_offset, interval;
+ int reserved_offset;
+ uint16_t sf;
+ uint8_t bd_addr[6];
proto_item *item;
proto_item *sub_item;
proto_tree *sub_tree;
@@ -1159,7 +1165,7 @@ dissect_periodic_sync_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset, pac
offset += 2;
/* Sync Info */
- sf = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
+ sf = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
item = proto_tree_add_item_ret_uint(btle_tree, hf_control_sync_info_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &sync_offset);
proto_tree_add_item(btle_tree, hf_control_sync_info_offset_units, tvb, offset, 2, ENC_LITTLE_ENDIAN);
@@ -1205,7 +1211,7 @@ dissect_periodic_sync_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset, pac
proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_phys, ett_phys, hfx_control_phys, ENC_NA);
offset += 1;
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, bd_addr);
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, bd_addr);
proto_tree_add_item(btle_tree, hf_control_sync_sync_conn_event_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
@@ -1213,10 +1219,10 @@ dissect_periodic_sync_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset, pac
return offset;
}
-static gint
-dissect_cis_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_cis_req(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
- guint32 interval;
+ uint32_t interval;
proto_item *item;
proto_tree_add_item(btle_tree, hf_control_cig_id, tvb, offset, 1, ENC_NA);
@@ -1225,33 +1231,33 @@ dissect_cis_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
proto_tree_add_item(btle_tree, hf_control_cis_id, tvb, offset, 1, ENC_NA);
offset += 1;
- proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_m_to_s_phy, ett_m_to_s_phy, hfx_control_m_to_s_phy, ENC_NA);
+ proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_c_to_p_phy, ett_c_to_p_phy, hfx_control_c_to_p_phy, ENC_NA);
offset += 1;
- proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_s_to_m_phy, ett_s_to_m_phy, hfx_control_s_to_m_phy, ENC_NA);
+ proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_p_to_c_phy, ett_p_to_c_phy, hfx_control_p_to_c_phy, ENC_NA);
offset += 1;
- proto_tree_add_item(btle_tree, hf_control_max_sdu_m_to_s, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_max_sdu_c_to_p, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(btle_tree, hf_control_rfu_1, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(btle_tree, hf_control_framed, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
- proto_tree_add_item(btle_tree, hf_control_max_sdu_s_to_m, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_max_sdu_p_to_c, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(btle_tree, hf_control_rfu_2, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
- proto_tree_add_item(btle_tree, hf_control_sdu_interval_m_to_s, tvb, offset, 3, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_sdu_interval_c_to_p, tvb, offset, 3, ENC_LITTLE_ENDIAN);
proto_tree_add_item(btle_tree, hf_control_rfu_3, tvb, offset, 3, ENC_LITTLE_ENDIAN);
offset += 3;
- proto_tree_add_item(btle_tree, hf_control_sdu_interval_s_to_m, tvb, offset, 3, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_sdu_interval_p_to_c, tvb, offset, 3, ENC_LITTLE_ENDIAN);
proto_tree_add_item(btle_tree, hf_control_rfu_4, tvb, offset, 3, ENC_LITTLE_ENDIAN);
offset += 3;
- proto_tree_add_item(btle_tree, hf_control_max_pdu_m_to_s, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_max_pdu_c_to_p, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
- proto_tree_add_item(btle_tree, hf_control_max_pdu_s_to_m, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(btle_tree, hf_control_max_pdu_p_to_c, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_tree_add_item(btle_tree, hf_control_num_sub_events, tvb, offset, 1, ENC_NA);
@@ -1260,14 +1266,14 @@ dissect_cis_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
proto_tree_add_item(btle_tree, hf_control_sub_interval, tvb, offset, 3, ENC_LITTLE_ENDIAN);
offset += 3;
- proto_tree_add_item(btle_tree, hf_control_bn_m_to_s, tvb, offset, 1, ENC_NA);
- proto_tree_add_item(btle_tree, hf_control_bn_s_to_m, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(btle_tree, hf_control_bn_c_to_p, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(btle_tree, hf_control_bn_p_to_c, tvb, offset, 1, ENC_NA);
offset += 1;
- proto_tree_add_item(btle_tree, hf_control_ft_m_to_s, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(btle_tree, hf_control_ft_c_to_p, tvb, offset, 1, ENC_NA);
offset += 1;
- proto_tree_add_item(btle_tree, hf_control_ft_s_to_m, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(btle_tree, hf_control_ft_p_to_c, tvb, offset, 1, ENC_NA);
offset += 1;
item = proto_tree_add_item_ret_uint(btle_tree, hf_control_iso_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &interval);
@@ -1286,8 +1292,8 @@ dissect_cis_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_cis_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_cis_rsp(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_cis_offset_min, tvb, offset, 3, ENC_LITTLE_ENDIAN);
offset += 3;
@@ -1301,8 +1307,8 @@ dissect_cis_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_cis_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_cis_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
@@ -1322,8 +1328,8 @@ dissect_cis_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_cis_terminate_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_cis_terminate_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_cig_id, tvb, offset, 1, ENC_NA);
offset += 1;
@@ -1337,8 +1343,8 @@ dissect_cis_terminate_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_power_control_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_power_control_req(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_pwr_phy, ett_pwr_phy, hfx_control_pwr_phy, ENC_NA);
offset += 1;
@@ -1353,8 +1359,8 @@ dissect_power_control_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
}
-static gint
-dissect_power_control_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_power_control_rsp(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_pwrflags, ett_pwrflags, hfx_control_pwrflags, ENC_NA);
offset += 1;
@@ -1371,8 +1377,8 @@ dissect_power_control_rsp(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_power_control_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_power_control_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_pwr_phy, ett_pwr_phy, hfx_control_pwr_phy, ENC_NA);
offset += 1;
@@ -1389,8 +1395,8 @@ dissect_power_control_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_subrate_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_subrate_req(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_subrate_factor_min, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
@@ -1410,8 +1416,8 @@ dissect_subrate_req(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_subrate_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_subrate_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_subrate_factor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
@@ -1431,8 +1437,8 @@ dissect_subrate_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_channel_reporting_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_channel_reporting_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_channel_reporting_enable, tvb, offset, 1, ENC_NA);
offset += 1;
@@ -1446,8 +1452,8 @@ dissect_channel_reporting_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
return offset;
}
-static gint
-dissect_channel_status_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
+static int
+dissect_channel_status_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset)
{
proto_tree_add_item(btle_tree, hf_control_channel_classification, tvb, offset, 10, ENC_NA);
offset += 10;
@@ -1456,8 +1462,8 @@ dissect_channel_status_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset)
}
-static gint
-dissect_periodic_sync_wr_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset, packet_info *pinfo, guint32 interface_id, guint32 adapter_id)
+static int
+dissect_periodic_sync_wr_ind(tvbuff_t *tvb, proto_tree *btle_tree, int offset, packet_info *pinfo, uint32_t interface_id, uint32_t adapter_id)
{
/* The first part of LL_PERIODIC_SYNC_WR_IND is identical to LL_PERIODIC_SYNC_IND */
offset += dissect_periodic_sync_ind(tvb, btle_tree, offset, pinfo, interface_id, adapter_id);
@@ -1480,8 +1486,8 @@ dissect_periodic_sync_wr_ind(tvbuff_t *tvb, proto_tree *btle_tree, gint offset,
return offset;
}
-static gint
-dissect_ctrl_pdu_without_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *btle_tree, gint offset)
+static int
+dissect_ctrl_pdu_without_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *btle_tree, int offset)
{
if (tvb_reported_length_remaining(tvb, offset) > 3) {
proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
@@ -1491,6 +1497,45 @@ dissect_ctrl_pdu_without_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *btl
return offset;
}
+static int
+dissect_crc(tvbuff_t *tvb,
+ proto_tree *btle_tree,
+ int offset,
+ packet_info *pinfo,
+ uint32_t length,
+ const connection_info_t *connection_info,
+ const btle_context_t *btle_context,
+ uint32_t access_address)
+{
+ /* BT spec Vol 6, Part B, Section 1.2: CRC is big endian and bits in byte are flipped */
+ uint32_t packet_crc = reverse_bits_per_byte(tvb_get_ntoh24(tvb, offset));
+ proto_item *sub_item = proto_tree_add_uint(btle_tree, hf_crc, tvb, offset, 3, packet_crc);
+
+ if (btle_context && btle_context->crc_checked_at_capture) {
+ if (!btle_context->crc_valid_at_capture) {
+ expert_add_info(pinfo, sub_item, &ei_crc_incorrect);
+ }
+ } else if ((access_address == ACCESS_ADDRESS_ADVERTISING) || connection_info) {
+ /* CRC can be calculated */
+ uint32_t crc_init;
+
+ if (access_address == ACCESS_ADDRESS_ADVERTISING) {
+ crc_init = 0x555555;
+ } else {
+ crc_init = connection_info->crc_init;
+ }
+
+ uint32_t crc = btle_crc(tvb, length, crc_init);
+ if (packet_crc != crc) {
+ expert_add_info(pinfo, sub_item, &ei_crc_incorrect);
+ }
+ } else {
+ expert_add_info(pinfo, sub_item, &ei_crc_cannot_be_determined);
+ }
+
+ return 3;
+}
+
/* Checks if it is possible to add the frame at the given index
* to the given control procedure context.
*
@@ -1498,26 +1543,26 @@ dissect_ctrl_pdu_without_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *btl
* Therefore this function can be used to add an LL_UNKNOWN_RSP to
* a completed connection parameter update procedure.
*/
-static gboolean
+static bool
control_proc_can_add_frame_even_if_complete(packet_info *pinfo,
control_proc_info_t *last_control_proc_info,
- guint8 proc_opcode,
- guint frame_num)
+ uint8_t proc_opcode,
+ unsigned frame_num)
{
if (frame_num == 0)
- return FALSE; /* This function must be used to add a frame to an ongoing procedure */
+ return false; /* This function must be used to add a frame to an ongoing procedure */
/* We need to check if the control procedure has been initiated. */
if (!last_control_proc_info)
- return FALSE;
+ return false;
/* And that the new frame belongs to this control procedure */
if (last_control_proc_info->proc_opcode != proc_opcode)
- return FALSE;
+ return false;
/* Previous frame has not yet been added. */
if (last_control_proc_info->frames[frame_num - 1] == 0)
- return FALSE;
+ return false;
/* We need to check if we can add this frame at this index
* in the control procedure sequence. */
@@ -1525,48 +1570,48 @@ control_proc_can_add_frame_even_if_complete(packet_info *pinfo,
/* The first time we visit the frame, we just need to check that the
* spot is empty. */
if (!pinfo->fd->visited && last_control_proc_info->frames[frame_num])
- return FALSE; /* Another opcode has already been added to the procedure at this index */
+ return false; /* Another opcode has already been added to the procedure at this index */
/* At later visits, we need to check that we are not replacing the frame with
* another frame. */
if (pinfo->fd->visited && (last_control_proc_info->frames[frame_num] != pinfo->num))
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
-static gboolean
-control_proc_is_complete(guint32 frame_num, control_proc_info_t const *last_control_proc_info)
+static bool
+control_proc_is_complete(uint32_t frame_num, control_proc_info_t const *last_control_proc_info)
{
if (last_control_proc_info->last_frame != 0 &&
frame_num > last_control_proc_info->last_frame)
- return TRUE;
+ return true;
- return FALSE;
+ return false;
}
-static gboolean
+static bool
control_proc_can_add_frame(packet_info *pinfo,
control_proc_info_t *last_control_proc_info,
- guint8 proc_opcode,
- guint frame_num)
+ uint8_t proc_opcode,
+ unsigned frame_num)
{
if (!control_proc_can_add_frame_even_if_complete(pinfo,
last_control_proc_info,
proc_opcode,
frame_num))
- return FALSE;
+ return false;
/* We check that we are not adding a frame to a completed procedure. */
if (control_proc_is_complete(pinfo->num, last_control_proc_info))
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
static void
-control_proc_complete_if_instant_reached(guint frame_num,
- guint16 event_counter,
+control_proc_complete_if_instant_reached(unsigned frame_num,
+ uint16_t event_counter,
control_proc_info_t *last_control_proc_info)
{
/* We need to check if the control procedure has been initiated. */
@@ -1588,8 +1633,8 @@ control_proc_complete_if_instant_reached(guint frame_num,
}
}
-static gboolean
-control_proc_contains_instant(guint8 proc_opcode)
+static bool
+control_proc_contains_instant(uint8_t proc_opcode)
{
switch (proc_opcode)
{
@@ -1597,30 +1642,30 @@ control_proc_contains_instant(guint8 proc_opcode)
case LL_CTRL_OPCODE_CHANNEL_MAP_IND:
case LL_CTRL_OPCODE_CONNECTION_PARAM_REQ:
case LL_CTRL_OPCODE_PHY_REQ:
- return TRUE;
+ return true;
default:
- return FALSE;
+ return false;
}
}
/* Returns true if this frame contains an collision violating the specification.
*
* See Core_v5.2, Vol 6, Part B, Section 5.3 */
-static gboolean
+static bool
control_proc_invalid_collision(packet_info const *pinfo,
control_proc_info_t const *control_proc_other,
- guint8 proc_opcode)
+ uint8_t proc_opcode)
{
if (!control_proc_other)
- return FALSE;
+ return false;
if (control_proc_is_complete(pinfo->num, control_proc_other))
- return FALSE;
+ return false;
/* Both procedures must contain an instant to be marked as incompatible. */
if (!control_proc_contains_instant(control_proc_other->proc_opcode) ||
!control_proc_contains_instant(proc_opcode))
- return FALSE;
+ return false;
/* From the Core Spec:
*
@@ -1632,9 +1677,9 @@ control_proc_invalid_collision(packet_info const *pinfo,
* time, there is a procedure violation.
*/
if (control_proc_other->frames[1] && (control_proc_other->frames[1] < pinfo->num))
- return TRUE;
+ return true;
else
- return FALSE;
+ return false;
}
/* Mark the start of a new control procedure.
@@ -1653,7 +1698,7 @@ control_proc_start(tvbuff_t *tvb,
proto_item *control_proc_item,
wmem_tree_t *control_proc_tree,
control_proc_info_t const *control_proc_other_direction,
- guint8 opcode)
+ uint8_t opcode)
{
if (control_proc_invalid_collision(pinfo,
control_proc_other_direction,
@@ -1682,7 +1727,7 @@ control_proc_start(tvbuff_t *tvb,
if (proc_info && proc_info->proc_opcode == opcode) {
proto_item *sub_item;
- for (guint i = 1; i < sizeof(proc_info->frames)/sizeof(proc_info->frames[0]); i++) {
+ for (unsigned i = 1; i < array_length(proc_info->frames); i++) {
if (proc_info->frames[i]) {
sub_item = proto_tree_add_uint(btle_tree, hf_response_in_frame, tvb, 0, 0, proc_info->frames[i]);
proto_item_set_generated(sub_item);
@@ -1704,11 +1749,11 @@ control_proc_start(tvbuff_t *tvb,
static void control_proc_add_frame(tvbuff_t *tvb,
packet_info *pinfo,
proto_tree *btle_tree,
- guint8 opcode,
- guint32 direction,
+ uint8_t opcode,
+ uint32_t direction,
control_proc_info_t *last_control_proc_info,
control_proc_info_t const *control_proc_other_direction,
- guint frame_num)
+ unsigned frame_num)
{
proto_item *item;
@@ -1722,7 +1767,7 @@ static void control_proc_add_frame(tvbuff_t *tvb,
!control_proc_is_complete(pinfo->num, control_proc_other_direction) &&
control_proc_contains_instant(last_control_proc_info->proc_opcode) &&
control_proc_contains_instant(control_proc_other_direction->proc_opcode)) {
- if (direction == BTLE_DIR_MASTER_SLAVE &&
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL &&
opcode != LL_CTRL_OPCODE_REJECT_IND &&
opcode != LL_CTRL_OPCODE_REJECT_EXT_IND) {
/* Continuing a control procedure when the peer has initiated an incompatible control procedure.
@@ -1739,11 +1784,11 @@ static void control_proc_add_frame(tvbuff_t *tvb,
static void control_proc_add_last_frame(tvbuff_t *tvb,
packet_info *pinfo,
proto_tree *btle_tree,
- guint8 opcode,
- guint32 direction,
+ uint8_t opcode,
+ uint32_t direction,
control_proc_info_t *last_control_proc_info,
control_proc_info_t const *control_proc_other_direction,
- guint frame_num)
+ unsigned frame_num)
{
control_proc_add_frame(tvb,
pinfo,
@@ -1762,12 +1807,12 @@ static void control_proc_add_frame_with_instant(tvbuff_t *tvb,
packet_info *pinfo,
proto_tree *btle_tree,
const btle_context_t *btle_context,
- guint8 opcode,
- guint32 direction,
+ uint8_t opcode,
+ uint32_t direction,
control_proc_info_t *last_control_proc_info,
control_proc_info_t const *control_proc_other_direction,
- guint frame_num,
- guint16 instant)
+ unsigned frame_num,
+ uint16_t instant)
{
if (btle_context && btle_context->event_counter_valid) {
control_proc_add_frame(tvb,
@@ -1794,7 +1839,7 @@ static void control_proc_add_frame_with_instant(tvbuff_t *tvb,
}
static void
-dissect_ad_eir(tvbuff_t *tvb, guint32 interface_id, guint32 adapter_id, guint32 frame_number, guint8 *src_bd_addr, packet_info *pinfo, proto_tree *tree)
+dissect_ad_eir(tvbuff_t *tvb, uint32_t interface_id, uint32_t adapter_id, uint32_t frame_number, uint8_t *src_bd_addr, packet_info *pinfo, proto_tree *tree)
{
bluetooth_eir_ad_data_t *ad_data = wmem_new0(pinfo->pool, bluetooth_eir_ad_data_t);
ad_data->interface_id = interface_id;
@@ -1802,23 +1847,23 @@ dissect_ad_eir(tvbuff_t *tvb, guint32 interface_id, guint32 adapter_id, guint32
call_dissector_with_data(btcommon_ad_handle, tvb, pinfo, tree, ad_data);
if (pinfo->fd->visited)
return;
- for (gint offset = 0;; ) {
- guint remain = tvb_reported_length_remaining(tvb, offset);
- guint length;
- guint8 opcode;
+ for (int offset = 0;; ) {
+ unsigned remain = tvb_reported_length_remaining(tvb, offset);
+ unsigned length;
+ uint8_t opcode;
if (remain < 1)
break;
- length = tvb_get_guint8(tvb, offset);
+ length = tvb_get_uint8(tvb, offset);
++offset;
if (length <= 0)
continue;
--remain;
if (remain < length)
break;
- opcode = tvb_get_guint8(tvb, offset);
+ opcode = tvb_get_uint8(tvb, offset);
if (opcode == 0x2c && length >= 34) {
- guint seed_access_address = tvb_get_guint32(tvb, offset + 14, ENC_LITTLE_ENDIAN);
- guint32 trunc_seed_access_address = seed_access_address & 0x0041ffff;
+ unsigned seed_access_address = tvb_get_uint32(tvb, offset + 14, ENC_LITTLE_ENDIAN);
+ uint32_t trunc_seed_access_address = seed_access_address & 0x0041ffff;
broadcastiso_connection_info_t *nconnection_info;
wmem_tree_key_t key[5];
@@ -1839,7 +1884,7 @@ dissect_ad_eir(tvbuff_t *tvb, guint32 interface_id, guint32 adapter_id, guint32
nconnection_info->access_address = seed_access_address;
if (src_bd_addr)
- memcpy(nconnection_info->master_bd_addr, src_bd_addr, 6);
+ memcpy(nconnection_info->central_bd_addr, src_bd_addr, 6);
wmem_tree_insert32_array(broadcastiso_connection_info_tree, key, nconnection_info);
}
@@ -1847,44 +1892,65 @@ dissect_ad_eir(tvbuff_t *tvb, guint32 interface_id, guint32 adapter_id, guint32
}
}
-static gint
-dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+static uint8_t
+guess_btle_pdu_type_from_access(uint32_t interface_id,
+ uint32_t adapter_id,
+ uint32_t access_address)
{
- proto_item *btle_item;
- proto_tree *btle_tree;
- proto_item *sub_item;
- proto_tree *sub_tree;
- gint offset = 0;
- guint32 access_address, length;
- tvbuff_t *next_tvb;
- guint8 *dst_bd_addr;
- guint8 *src_bd_addr;
- static const guint8 broadcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- connection_info_t *connection_info = NULL;
- wmem_tree_t *wmem_tree;
- wmem_tree_key_t key[5], ae_had_key[4];
- guint32 interface_id;
- guint32 adapter_id;
- guint32 connection_access_address;
- guint32 frame_number;
- enum {CRC_INDETERMINATE,
- CRC_CAN_BE_CALCULATED,
- CRC_INCORRECT,
- CRC_CORRECT} crc_status = CRC_INDETERMINATE;
- guint32 crc_init = 0x555555; /* default to advertising channel's value */
- guint32 packet_crc;
- const btle_context_t *btle_context = NULL;
- bluetooth_data_t *bluetooth_data = NULL;
- ubertooth_data_t *ubertooth_data = NULL;
- gint previous_proto;
- wmem_list_frame_t *list_data;
- proto_item *item;
- guint item_value;
- guint8 btle_pdu_type = BTLE_PDU_TYPE_UNKNOWN;
+ wmem_tree_key_t key[5];
+ wmem_tree_t *wmem_tree;
+ uint32_t broadcast_iso_seed_access_address = access_address & 0x0041ffff;
+
+ /* No context to provide us with physical channel pdu type, make an assumption from the access address */
+ if (access_address == ACCESS_ADDRESS_ADVERTISING) {
+ return BTLE_PDU_TYPE_ADVERTISING;
+ }
+
+ /* Check if it is a connection context. */
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &access_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_info_tree, key);
+ if (wmem_tree) {
+ /* Connection. */
+ return BTLE_PDU_TYPE_DATA;
+ }
- list_data = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(periodic_adv_info_tree, key);
+ if (wmem_tree) {
+ /* Periodic advertiser. */
+ return BTLE_PDU_TYPE_ADVERTISING;
+ }
+
+ key[2].key = &broadcast_iso_seed_access_address;
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(broadcastiso_connection_info_tree, key);
+ if (wmem_tree) {
+ /* Broadcast ISO. */
+ return BTLE_PDU_TYPE_BROADCASTISO;
+ }
+
+ /* Default to data. */
+ return BTLE_PDU_TYPE_DATA;
+}
+
+static const btle_context_t * get_btle_context(packet_info *pinfo,
+ void *data,
+ uint32_t *adapter_id_out,
+ uint32_t *interface_id_out)
+{
+ const btle_context_t * btle_context = NULL;
+ bluetooth_data_t *bluetooth_data = NULL;
+ ubertooth_data_t *ubertooth_data = NULL;
+
+ wmem_list_frame_t * list_data = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
if (list_data) {
- previous_proto = GPOINTER_TO_INT(wmem_list_frame_data(list_data));
+ int previous_proto = GPOINTER_TO_INT(wmem_list_frame_data(list_data));
if ((previous_proto == proto_btle_rf)||(previous_proto == proto_nordic_ble)) {
btle_context = (const btle_context_t *) data;
@@ -1898,363 +1964,522 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
}
}
- src_bd_addr = (guint8 *) wmem_alloc(pinfo->pool, 6);
- dst_bd_addr = (guint8 *) wmem_alloc(pinfo->pool, 6);
+ if (bluetooth_data)
+ *interface_id_out = bluetooth_data->interface_id;
+ else if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
+ *interface_id_out = pinfo->rec->rec_header.packet_header.interface_id;
+ else
+ *interface_id_out = HCI_INTERFACE_DEFAULT;
+
+ if (ubertooth_data)
+ *adapter_id_out = ubertooth_data->bus_id << 8 | ubertooth_data->device_address;
+ else if (bluetooth_data)
+ *adapter_id_out = bluetooth_data->adapter_id;
+ else
+ *adapter_id_out = HCI_ADAPTER_DEFAULT;
- if (btle_context && btle_context->crc_checked_at_capture) {
- crc_status = btle_context->crc_valid_at_capture ? CRC_CORRECT : CRC_INCORRECT;
- }
+ return btle_context;
+}
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "LE LL");
+static int
+dissect_btle_adv(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *btle_tree,
+ const btle_context_t *btle_context,
+ uint32_t adapter_id,
+ uint32_t interface_id,
+ uint32_t access_address)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ int offset = 0;
+ uint32_t length;
+ tvbuff_t *next_tvb;
+ uint8_t *dst_bd_addr;
+ uint8_t *src_bd_addr;
+ static const uint8_t broadcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ connection_info_t *connection_info = NULL;
+ wmem_tree_t *wmem_tree;
+ wmem_tree_key_t key[5], ae_had_key[4];
- btle_item = proto_tree_add_item(tree, proto_btle, tvb, offset, -1, ENC_NA);
- btle_tree = proto_item_add_subtree(btle_item, ett_btle);
+ uint32_t connection_access_address;
- sub_item = proto_tree_add_item(btle_tree, hf_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- access_address = tvb_get_letohl(tvb, offset);
- if (btle_context) {
- switch(btle_context->aa_category) {
- case E_AA_MATCHED:
- expert_add_info(pinfo, sub_item, &ei_access_address_matched);
- break;
- case E_AA_ILLEGAL:
- expert_add_info(pinfo, sub_item, &ei_access_address_illegal);
- break;
- case E_AA_BIT_ERRORS:
- expert_add_info(pinfo, sub_item, &ei_access_address_bit_errors);
- break;
- default:
- break;
+ proto_item *item;
+ unsigned item_value;
+
+ proto_item *advertising_header_item;
+ proto_tree *advertising_header_tree;
+ proto_item *link_layer_data_item;
+ proto_tree *link_layer_data_tree;
+ uint8_t header, pdu_type;
+ bool ch_sel_valid = false, tx_add_valid = false, rx_add_valid = false;
+ bool is_periodic_adv = false;
+
+ src_bd_addr = (uint8_t *) wmem_alloc(pinfo->pool, 6);
+ dst_bd_addr = (uint8_t *) wmem_alloc(pinfo->pool, 6);
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &access_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_info_tree, key);
+ if (!wmem_tree) {
+ /* Check periodic advertising tree */
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(periodic_adv_info_tree, key);
+ if (wmem_tree) {
+ is_periodic_adv = true;
}
}
- offset += 4;
- if (btle_context && btle_context->phy == LE_CODED_PHY) {
- proto_tree_add_item(btle_tree, hf_coding_indicator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ if (wmem_tree) {
+ connection_info = (connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
+ if (connection_info) {
+ set_address(&pinfo->net_src, AT_ETHER, 6, connection_info->central_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ memcpy(src_bd_addr, connection_info->central_bd_addr, 6);
+ }
}
- if (bluetooth_data)
- interface_id = bluetooth_data->interface_id;
- else if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)
- interface_id = pinfo->rec->rec_header.packet_header.interface_id;
- else
- interface_id = HCI_INTERFACE_DEFAULT;
+ advertising_header_item = proto_tree_add_item(btle_tree, hf_advertising_header, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ advertising_header_tree = proto_item_add_subtree(advertising_header_item, ett_advertising_header);
- if (ubertooth_data)
- adapter_id = ubertooth_data->bus_id << 8 | ubertooth_data->device_address;
- else if (bluetooth_data)
- adapter_id = bluetooth_data->adapter_id;
- else
- adapter_id = HCI_ADAPTER_DEFAULT;
+ header = tvb_get_uint8(tvb, offset);
+ pdu_type = header & 0x0F;
- frame_number = pinfo->num;
+ switch (pdu_type) {
+ case 0x00: /* ADV_IND */
+ ch_sel_valid = true;
+ /* Fallthrough */
+ case 0x02: /* ADV_NONCONN_IND */
+ case 0x06: /* ADV_SCAN_IND */
+ case 0x04: /* SCAN_RSP */
+ tx_add_valid = true;
+ break;
+ case 0x07: /* ADV_EXT_IND / AUX_ADV_IND / AUX_SYNC_IND / AUX_CHAIN_IND / AUX_SCAN_RSP */
+ case 0x08: /* AUX_CONNECT_RSP */
+ {
+ /* 0 + header, 1 = len, 2 = ext_len/adv-mode, 3 = flags */
+ uint8_t ext_header_flags = tvb_get_uint8(tvb, offset + 3);
- if (btle_context) {
- btle_pdu_type = btle_context->pdu_type;
+ ch_sel_valid = false;
+ tx_add_valid = (ext_header_flags & 0x01) != 0;
+ rx_add_valid = (ext_header_flags & 0x02) != 0;
+ break;
+ }
+ case 0x01: /* ADV_DIRECT_IND */
+ case 0x05: /* CONNECT_IND or AUX_CONNECT_REQ */
+ if (btle_context && btle_context->channel >= 37) {
+ /* CONNECT_IND */
+ ch_sel_valid = true;
+ }
+ /* Fallthrough */
+ case 0x03: /* SCAN_REQ or AUX_SCAN_REQ */
+ tx_add_valid = true;
+ rx_add_valid = true;
+ break;
}
- if (btle_pdu_type == BTLE_PDU_TYPE_UNKNOWN) {
- /* No context to provide us with physical channel pdu type, make an assumption from the access address */
- btle_pdu_type = access_address == ACCESS_ADDRESS_ADVERTISING ? BTLE_PDU_TYPE_ADVERTISING : BTLE_PDU_TYPE_DATA;
+ proto_item_append_text(advertising_header_item, " (PDU Type: %s", adv_pdu_type_str_get(btle_context, pdu_type, is_periodic_adv));
+ item = proto_tree_add_item(advertising_header_tree, hf_advertising_header_pdu_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_item_append_text(item, " %s", adv_pdu_type_str_get(btle_context, pdu_type, is_periodic_adv));
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+
+ if (ch_sel_valid) {
+ proto_item_append_text(advertising_header_item, ", ChSel: %s",
+ tfs_get_string(header & 0x20, &tfs_ch_sel));
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_ch_sel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ } else {
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
}
- if (btle_pdu_type == BTLE_PDU_TYPE_ADVERTISING) {
- proto_item *advertising_header_item;
- proto_tree *advertising_header_tree;
- proto_item *link_layer_data_item;
- proto_tree *link_layer_data_tree;
- guint8 header, pdu_type;
- gboolean ch_sel_valid = FALSE, tx_add_valid = FALSE, rx_add_valid = FALSE;
-
- if (crc_status == CRC_INDETERMINATE) {
- /* Advertising channel CRCs can aways be calculated, because CRCInit is always known. */
- crc_status = CRC_CAN_BE_CALCULATED;
- }
+ if (tx_add_valid) {
+ proto_item_append_text(advertising_header_item, ", TxAdd: %s",
+ tfs_get_string(header & 0x40, &tfs_random_public));
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_randomized_tx, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ } else {
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_3, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ }
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &access_address;
- key[3].length = 0;
- key[3].key = NULL;
+ if (rx_add_valid) {
+ proto_item_append_text(advertising_header_item, ", RxAdd: %s",
+ tfs_get_string(header & 0x80, &tfs_random_public));
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_randomized_rx, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ } else {
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_4, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ }
- wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_info_tree, key);
- if (wmem_tree) {
- connection_info = (connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
- if (connection_info) {
- set_address(&pinfo->net_src, AT_ETHER, 6, connection_info->master_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
- memcpy(src_bd_addr, connection_info->master_bd_addr, 6);
- }
- }
+ proto_item_append_text(advertising_header_item, ")");
- advertising_header_item = proto_tree_add_item(btle_tree, hf_advertising_header, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- advertising_header_tree = proto_item_add_subtree(advertising_header_item, ett_advertising_header);
+ col_set_str(pinfo->cinfo, COL_INFO, adv_pdu_type_str_get(btle_context, pdu_type, is_periodic_adv));
- header = tvb_get_guint8(tvb, offset);
- pdu_type = header & 0x0F;
+ offset += 1;
- switch (pdu_type) {
- case 0x00: /* ADV_IND */
- ch_sel_valid = TRUE;
- /* Fallthrough */
- case 0x02: /* ADV_NONCONN_IND */
- case 0x06: /* ADV_SCAN_IND */
- case 0x04: /* SCAN_RSP */
- tx_add_valid = TRUE;
- break;
- case 0x07: /* ADV_EXT_IND / AUX_ADV_IND / AUX_SYNC_IND / AUX_CHAIN_IND / AUX_SCAN_RSP */
- case 0x08: /* AUX_CONNECT_RSP */
- {
- /* 0 + header, 1 = len, 2 = ext_len/adv-mode, 3 = flags */
- guint8 ext_header_flags = tvb_get_guint8(tvb, offset + 3);
+ proto_tree_add_item(advertising_header_tree, hf_advertising_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ proto_item_set_hidden(item);
+ offset += 1;
- ch_sel_valid = FALSE;
- tx_add_valid = (ext_header_flags & 0x01) != 0;
- rx_add_valid = (ext_header_flags & 0x02) != 0;
- break;
+ switch (pdu_type) {
+ case 0x00: /* ADV_IND */
+ case 0x02: /* ADV_NONCONN_IND */
+ case 0x06: /* ADV_SCAN_IND */
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, src_bd_addr);
+
+ set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+
+ set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+
+ if (!pinfo->fd->visited) {
+ address *addr;
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
}
- case 0x01: /* ADV_DIRECT_IND */
- case 0x05: /* CONNECT_IND or AUX_CONNECT_REQ */
- if (btle_context && btle_context->channel >= 37) {
- /* CONNECT_IND */
- ch_sel_valid = TRUE;
- }
- /* Fallthrough */
- case 0x03: /* SCAN_REQ or AUX_SCAN_REQ */
- tx_add_valid = TRUE;
- rx_add_valid = TRUE;
- break;
+
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ dissect_ad_eir(next_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, btle_tree);
}
- proto_item_append_text(advertising_header_item, " (PDU Type: %s", adv_pdu_type_str_get(btle_context, pdu_type));
- item = proto_tree_add_item(advertising_header_tree, hf_advertising_header_pdu_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_item_append_text(item, " %s", adv_pdu_type_str_get(btle_context, pdu_type));
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
- if (ch_sel_valid) {
- proto_item_append_text(advertising_header_item, ", ChSel: %s",
- tfs_get_string(header & 0x20, &tfs_ch_sel));
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_ch_sel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- } else {
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ break;
+ case 0x01: /* ADV_DIRECT_IND */
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, src_bd_addr);
+ offset = dissect_bd_addr(hf_target_addresss, pinfo, btle_tree, tvb, offset, false, interface_id, adapter_id, dst_bd_addr);
+
+ set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+
+ set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+
+ if (!pinfo->fd->visited) {
+ address *addr;
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
}
- if (tx_add_valid) {
- proto_item_append_text(advertising_header_item, ", TxAdd: %s",
- tfs_get_string(header & 0x40, &tfs_random_public));
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_randomized_tx, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- } else {
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_3, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ break;
+ case 0x03: /* SCAN_REQ */
+ offset = dissect_bd_addr(hf_scanning_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, src_bd_addr);
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, false, interface_id, adapter_id, dst_bd_addr);
+
+ set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+
+ set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+
+ if (!pinfo->fd->visited) {
+ address *addr;
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
}
- if (rx_add_valid) {
- proto_item_append_text(advertising_header_item, ", RxAdd: %s",
- tfs_get_string(header & 0x80, &tfs_random_public));
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_randomized_rx, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- } else {
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_rfu_4, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ break;
+ case 0x04: /* SCAN_RSP */
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, src_bd_addr);
+
+ set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+
+ set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+
+ if (!pinfo->fd->visited) {
+ address *addr;
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
}
- proto_item_append_text(advertising_header_item, ")");
+ sub_item = proto_tree_add_item(btle_tree, hf_scan_response_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_scan_response_data);
- col_set_str(pinfo->cinfo, COL_INFO, adv_pdu_type_str_get(btle_context, pdu_type));
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ dissect_ad_eir(next_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, sub_tree);
+ }
- offset += 1;
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
- proto_tree_add_item(advertising_header_tree, hf_advertising_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
- proto_item_set_hidden(item);
- offset += 1;
+ break;
+ case 0x05: /* CONNECT_IND */
+ {
+ uint32_t connect_ind_crc_init;
- switch (pdu_type) {
- case 0x00: /* ADV_IND */
- case 0x02: /* ADV_NONCONN_IND */
- case 0x06: /* ADV_SCAN_IND */
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, src_bd_addr);
+ offset = dissect_bd_addr(hf_initiator_addresss, pinfo, btle_tree, tvb, offset, false, interface_id, adapter_id, src_bd_addr);
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, true, interface_id, adapter_id, dst_bd_addr);
- set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
+ copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
- set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
- if (!pinfo->fd->visited) {
- address *addr;
+ if (!pinfo->fd->visited) {
+ address *addr;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- }
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
+ }
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- dissect_ad_eir(next_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, btle_tree);
- }
+ link_layer_data_item = proto_tree_add_item(btle_tree, hf_link_layer_data, tvb, offset, 22, ENC_NA);
+ link_layer_data_tree = proto_item_add_subtree(link_layer_data_item, ett_link_layer_data);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ connection_access_address = tvb_get_letohl(tvb, offset);
+ offset += 4;
- break;
- case 0x01: /* ADV_DIRECT_IND */
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, src_bd_addr);
- offset = dissect_bd_addr(hf_target_addresss, pinfo, btle_tree, tvb, offset, FALSE, interface_id, adapter_id, dst_bd_addr);
+ proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_crc_init, tvb, offset, 3, ENC_LITTLE_ENDIAN, &connect_ind_crc_init);
+ offset += 3;
- set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_window_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 1;
- set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_window_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 2;
- if (!pinfo->fd->visited) {
- address *addr;
+ item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 2;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- }
+ item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%u msec)", item_value*10);
+ offset += 2;
- break;
- case 0x03: /* SCAN_REQ */
- offset = dissect_bd_addr(hf_scanning_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, src_bd_addr);
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, FALSE, interface_id, adapter_id, dst_bd_addr);
+ sub_item = proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_channel_map, tvb, offset, 5, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
- set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
+ offset += 5;
- set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_hop, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_sleep_clock_accuracy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- if (!pinfo->fd->visited) {
- address *addr;
+ if (!pinfo->fd->visited) {
+ connection_parameter_info_t *connection_parameter_info;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &connection_access_address;
+ key[3].length = 1;
+ key[3].key = &pinfo->num;
+ key[4].length = 0;
+ key[4].key = NULL;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- }
+ connection_info = wmem_new0(wmem_file_scope(), connection_info_t);
+ connection_info->interface_id = interface_id;
+ connection_info->adapter_id = adapter_id;
+ connection_info->access_address = connection_access_address;
+ connection_info->crc_init = connect_ind_crc_init;
- break;
- case 0x04: /* SCAN_RSP */
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, src_bd_addr);
+ memcpy(connection_info->central_bd_addr, src_bd_addr, 6);
+ memcpy(connection_info->peripheral_bd_addr, dst_bd_addr, 6);
- set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ /* We don't create control procedure context trees for BTLE_DIR_UNKNOWN,
+ * as the direction must be known for request/response matching. */
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
+ connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
- set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ wmem_tree_insert32_array(connection_info_tree, key, connection_info);
- if (!pinfo->fd->visited) {
- address *addr;
+ connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
+ connection_parameter_info->parameters_frame = pinfo->num;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ key[3].length = 1;
+ key[3].key = &pinfo->num;
+ wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
+ }
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- }
+ break;
+ }
+ case 0x07: /* ADV_EXT_IND / AUX_ADV_IND / AUX_SYNC_IND / AUX_CHAIN_IND / AUX_SCAN_RSP */
+ case 0x08: /* AUX_CONNECT_RSP */
+ {
+ uint8_t tmp, ext_header_len, flags, acad_len;
+ proto_item *ext_header_item, *ext_flags_item;
+ proto_tree *ext_header_tree, *ext_flags_tree;
+ uint32_t adi;
+ bool adi_present = false;
+ bool aux_pointer_present = false;
- sub_item = proto_tree_add_item(btle_tree, hf_scan_response_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_scan_response_data);
+ tmp = tvb_get_uint8(tvb, offset);
+ ext_header_len = acad_len = tmp & 0x3F;
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- dissect_ad_eir(next_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, sub_tree);
- }
+ ext_header_item = proto_tree_add_item(btle_tree, hf_extended_advertising_header, tvb, offset, ext_header_len + 1, ENC_NA);
+ ext_header_tree = proto_item_add_subtree(ext_header_item, ett_extended_advertising_header);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ proto_tree_add_item(ext_header_tree, hf_extended_advertising_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ext_header_tree, hf_extended_advertising_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- break;
- case 0x05: /* CONNECT_IND */
- offset = dissect_bd_addr(hf_initiator_addresss, pinfo, btle_tree, tvb, offset, FALSE, interface_id, adapter_id, src_bd_addr);
- offset = dissect_bd_addr(hf_advertising_address, pinfo, btle_tree, tvb, offset, TRUE, interface_id, adapter_id, dst_bd_addr);
+ if (ext_header_len > 0) {
+ ext_flags_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_flags, tvb, offset, 1, ENC_NA);
+ ext_flags_tree = proto_item_add_subtree(ext_flags_item, ett_extended_advertising_flags);
+
+ proto_tree_add_bitmask_list(ext_flags_tree, tvb, offset, 1, hfx_extended_advertising_flags, ENC_NA);
+ flags = tvb_get_uint8(tvb, offset);
+ offset += 1;
+
+ acad_len -= 1;
+ } else {
+ flags = 0;
+ }
+ if (flags & 0x01) {
+ /* Advertiser Address */
+ offset = dissect_bd_addr(hf_advertising_address, pinfo, ext_header_tree, tvb, offset, true, interface_id, adapter_id, src_bd_addr);
set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ acad_len -= 6;
+ } else if (!connection_info) {
+ const char * anon_str = "Anonymous";
+ clear_address(&pinfo->dl_src);
+ set_address(&pinfo->net_src, AT_STRINGZ, sizeof(*anon_str), anon_str);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ }
+
+ if (flags & 0x02) {
+ /* Target Address */
+ offset = dissect_bd_addr(hf_target_addresss, pinfo, ext_header_tree, tvb, offset, false, interface_id, adapter_id, dst_bd_addr);
set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
- if (!pinfo->fd->visited) {
- address *addr;
-
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ acad_len -= 6;
+ } else {
+ set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ }
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- }
+ if (flags & 0x04) {
+ uint32_t cte_time;
- link_layer_data_item = proto_tree_add_item(btle_tree, hf_link_layer_data, tvb, offset, 22, ENC_NA);
- link_layer_data_tree = proto_item_add_subtree(link_layer_data_item, ett_link_layer_data);
+ /* CTE Info */
+ sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_cte_info, tvb, offset, 1, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_cte_info);
- proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- connection_access_address = tvb_get_letohl(tvb, offset);
- offset += 4;
+ item = proto_tree_add_item_ret_uint(sub_tree, hf_extended_advertising_cte_info_time, tvb, offset, 1, ENC_LITTLE_ENDIAN, &cte_time);
+ proto_item_append_text(item, " (%u usec)", cte_time * 8);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_cte_info_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_cte_info_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_crc_init, tvb, offset, 3, ENC_LITTLE_ENDIAN);
- offset += 3;
+ acad_len -= 1;
+ }
- item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_window_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
- offset += 1;
+ if (flags & 0x08) {
+ /* AdvDataInfo */
+ sub_item = proto_tree_add_item_ret_uint(ext_header_tree, hf_extended_advertising_data_info, tvb, offset, 2, ENC_LITTLE_ENDIAN, &adi);
+ sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_data_info);
- item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_window_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_data_info_did, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_data_info_sid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
+ adi_present = true;
- item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
- offset += 2;
+ acad_len -= 2;
+ }
- proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ if (flags & 0x10) {
+ uint32_t aux_offset;
- item = proto_tree_add_item_ret_uint(link_layer_data_tree, hf_link_layer_data_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%u msec)", item_value*10);
+ /* Aux Pointer */
+ sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_aux_ptr, tvb, offset, 3, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_aux_pointer);
+
+ proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_ca, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_offset_units, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ tmp = tvb_get_uint8(tvb, offset);
+ offset += 1;
+
+ item = proto_tree_add_item_ret_uint(sub_tree, hf_extended_advertising_aux_ptr_aux_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &aux_offset);
+ proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_aux_phy, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_item_append_text(item, " (%u usec)", aux_offset * ((tmp & 0x80) != 0 ? 300 : 30));
offset += 2;
+ aux_pointer_present = true;
- sub_item = proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_channel_map, tvb, offset, 5, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+ acad_len -= 3;
+ }
- call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
- offset += 5;
+ if (flags & 0x20) {
+ uint32_t sync_offset, interval;
+ proto_item *sync_info_item;
+ proto_tree *sync_info_tree;
+ int reserved_offset;
+ uint16_t sf;
- proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_hop, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(link_layer_data_tree, hf_link_layer_data_sleep_clock_accuracy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ /* Sync Info */
+ sync_info_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_sync_info, tvb, offset, 18, ENC_NA);
+ sync_info_tree = proto_item_add_subtree(sync_info_item, ett_extended_advertising_sync_info);
if (!pinfo->fd->visited) {
connection_parameter_info_t *connection_parameter_info;
+ connection_access_address = tvb_get_uint32(tvb, offset + 9, ENC_LITTLE_ENDIAN);
+
key[0].length = 1;
key[0].key = &interface_id;
key[1].length = 1;
@@ -2262,7 +2487,7 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
key[2].length = 1;
key[2].key = &connection_access_address;
key[3].length = 1;
- key[3].key = &frame_number;
+ key[3].key = &pinfo->num;
key[4].length = 0;
key[4].key = NULL;
@@ -2271,17 +2496,17 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
connection_info->adapter_id = adapter_id;
connection_info->access_address = connection_access_address;
- memcpy(connection_info->master_bd_addr, src_bd_addr, 6);
- memcpy(connection_info->slave_bd_addr, dst_bd_addr, 6);
+ if (flags & 0x01)
+ memcpy(connection_info->central_bd_addr, src_bd_addr, 6);
/* We don't create control procedure context trees for BTLE_DIR_UNKNOWN,
- * as the direction must be known for request/response matching. */
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs =
- wmem_tree_new(wmem_file_scope());
- connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs =
- wmem_tree_new(wmem_file_scope());
+ * as the direction must be known for request/response matching. */
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
+ connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
- wmem_tree_insert32_array(connection_info_tree, key, connection_info);
+ wmem_tree_insert32_array(periodic_adv_info_tree, key, connection_info);
connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
connection_parameter_info->parameters_frame = pinfo->num;
@@ -2291,628 +2516,470 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
}
- break;
- case 0x07: /* ADV_EXT_IND / AUX_ADV_IND / AUX_SYNC_IND / AUX_CHAIN_IND / AUX_SCAN_RSP */
- case 0x08: /* AUX_CONNNECT_RSP */
- {
- guint8 tmp, ext_header_len, flags, acad_len;
- proto_item *ext_header_item, *ext_flags_item;
- proto_tree *ext_header_tree, *ext_flags_tree;
- guint32 adi;
- gboolean adi_present = FALSE;
- gboolean aux_pointer_present = FALSE;
-
- tmp = tvb_get_guint8(tvb, offset);
- ext_header_len = acad_len = tmp & 0x3F;
-
- ext_header_item = proto_tree_add_item(btle_tree, hf_extended_advertising_header, tvb, offset, ext_header_len + 1, ENC_NA);
- ext_header_tree = proto_item_add_subtree(ext_header_item, ett_extended_advertising_header);
-
- proto_tree_add_item(ext_header_tree, hf_extended_advertising_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ext_header_tree, hf_extended_advertising_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ sf = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
- if (ext_header_len > 0) {
- ext_flags_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_flags, tvb, offset, 1, ENC_NA);
- ext_flags_tree = proto_item_add_subtree(ext_flags_item, ett_extended_advertising_flags);
-
- proto_tree_add_bitmask_list(ext_flags_tree, tvb, offset, 1, hfx_extended_advertising_flags, ENC_NA);
- flags = tvb_get_guint8(tvb, offset);
- offset += 1;
-
- acad_len -= 1;
+ item = proto_tree_add_item_ret_uint(sync_info_tree, hf_extended_advertising_sync_info_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &sync_offset);
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_offset_units, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_offset_adjust, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ if (sync_offset > 0) {
+ proto_item_append_text(item, " (%u usec)", sync_offset * ((sf & 0x2000) != 0 ? 300 : 30) + ((sf & 0x4000) != 0 ? 2457600 : 0));
} else {
- flags = 0;
+ proto_item_append_text(item, " Cannot be represented");
}
+ offset += 2;
- if (flags & 0x01) {
- /* Advertiser Address */
- offset = dissect_bd_addr(hf_advertising_address, pinfo, ext_header_tree, tvb, offset, TRUE, interface_id, adapter_id, src_bd_addr);
- set_address(&pinfo->net_src, AT_ETHER, 6, src_bd_addr);
- copy_address_shallow(&pinfo->dl_src, &pinfo->net_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
-
- acad_len -= 6;
- } else if (!connection_info) {
- const char * anon_str = "Anonymous";
- clear_address(&pinfo->dl_src);
- set_address(&pinfo->net_src, AT_STRINGZ, sizeof(*anon_str), anon_str);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
- }
-
- if (flags & 0x02) {
- /* Target Address */
- offset = dissect_bd_addr(hf_target_addresss, pinfo, ext_header_tree, tvb, offset, FALSE, interface_id, adapter_id, dst_bd_addr);
- set_address(&pinfo->net_dst, AT_ETHER, 6, dst_bd_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
-
- acad_len -= 6;
- } else {
- set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
- }
+ item = proto_tree_add_item_ret_uint(sync_info_tree, hf_extended_advertising_sync_info_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &interval);
+ proto_item_append_text(item, " (%g msec)", interval * 1.25);
+ offset += 2;
- if (flags & 0x04) {
- guint32 cte_time;
+ sub_item = proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_channel_map, tvb, offset, 5, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
- /* CTE Info */
- sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_cte_info, tvb, offset, 1, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_cte_info);
+ call_dissector_with_data(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree, &reserved_offset);
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_sleep_clock_accuracy, tvb, offset + reserved_offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 5;
- item = proto_tree_add_item_ret_uint(sub_tree, hf_extended_advertising_cte_info_time, tvb, offset, 1, ENC_LITTLE_ENDIAN, &cte_time);
- proto_item_append_text(item, " (%u usec)", cte_time * 8);
- proto_tree_add_item(sub_tree, hf_extended_advertising_cte_info_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sub_tree, hf_extended_advertising_cte_info_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- acad_len -= 1;
- }
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_crc_init, tvb, offset, 3, ENC_LITTLE_ENDIAN);
+ offset += 3;
- if (flags & 0x08) {
- /* AdvDataInfo */
- sub_item = proto_tree_add_item_ret_uint(ext_header_tree, hf_extended_advertising_data_info, tvb, offset, 2, ENC_LITTLE_ENDIAN, &adi);
- sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_data_info);
+ proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_event_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(sub_tree, hf_extended_advertising_data_info_did, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sub_tree, hf_extended_advertising_data_info_sid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- adi_present = TRUE;
+ acad_len -= 18;
+ }
- acad_len -= 2;
- }
+ if (flags & 0x40) {
+ /* Tx Power */
+ proto_tree_add_item(ext_header_tree, hf_extended_advertising_tx_power, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- if (flags & 0x10) {
- guint32 aux_offset;
+ acad_len -= 1;
+ }
- /* Aux Pointer */
- sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_aux_ptr, tvb, offset, 3, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_aux_pointer);
+ if (acad_len > 0) {
+ sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_header_acad, tvb, offset, acad_len, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_acad);
- proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_ca, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_offset_units, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- tmp = tvb_get_guint8(tvb, offset);
- offset += 1;
+ /* Additional Controller Advertising Data */
+ next_tvb = tvb_new_subset_length(tvb, offset, acad_len);
+ dissect_ad_eir(next_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, sub_tree);
- item = proto_tree_add_item_ret_uint(sub_tree, hf_extended_advertising_aux_ptr_aux_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &aux_offset);
- proto_tree_add_item(sub_tree, hf_extended_advertising_aux_ptr_aux_phy, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_item_append_text(item, " (%u usec)", aux_offset * ((tmp & 0x80) != 0 ? 300 : 30));
- offset += 2;
- aux_pointer_present = TRUE;
+ offset += acad_len;
+ }
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ bool ad_processed = false;
+ if (btle_context && pdu_type == 0x07 && btle_context->aux_pdu_type_valid) {
+ bool ad_reassembled = false;
+ ae_had_info_t *ae_had_info = NULL;
+
+ switch (btle_context->aux_pdu_type) {
+ case 0x00: /* AUX_ADV_IND */
+ case 0x02: /* AUX_SYNC_IND */
+ case 0x03: /* AUX_SCAN_RSP */
+ if (aux_pointer_present) {
+ /* Beginning of new sequence of fragments */
+ if (!pinfo->fd->visited && adi_present) {
+ ae_had_info = wmem_new0(wmem_file_scope(), ae_had_info_t);
+ ae_had_info->first_frame_num=pinfo->num;
- acad_len -= 3;
- }
+ if (flags & 0x01) {
+ /* Copy Advertiser Address to reassemble AUX_CHAIN_IND */
+ copy_address_wmem(wmem_file_scope(), &ae_had_info->adv_addr, &pinfo->src);
+ }
- if (flags & 0x20) {
- guint32 sync_offset, interval;
- proto_item *sync_info_item;
- proto_tree *sync_info_tree;
- gint reserved_offset;
- guint16 sf;
+ ae_had_key[0].length = 1;
+ ae_had_key[0].key = &interface_id;
+ ae_had_key[1].length = 1;
+ ae_had_key[1].key = &adapter_id;
+ ae_had_key[2].length = 1;
+ ae_had_key[2].key = &adi;
+ ae_had_key[3].length = 0;
+ ae_had_key[3].key = NULL;
- /* Sync Info */
- sync_info_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_sync_info, tvb, offset, 18, ENC_NA);
- sync_info_tree = proto_item_add_subtree(sync_info_item, ett_extended_advertising_sync_info);
+ wmem_tree_insert32_array(adi_to_first_frame_tree, ae_had_key, ae_had_info);
- if (!pinfo->fd->visited) {
- connection_parameter_info_t *connection_parameter_info;
+ fragment_add_seq(&btle_ea_host_advertising_data_reassembly_table,
+ tvb, offset, pinfo,
+ ae_had_info->first_frame_num, NULL,
+ ae_had_info->fragment_counter,
+ tvb_captured_length_remaining(tvb, offset) - 3,
+ !ad_reassembled, 0);
- connection_access_address = tvb_get_guint32(tvb, offset + 9, ENC_LITTLE_ENDIAN);
+ ae_had_info->fragment_counter++;
+ }
+ ad_processed = true;
+ }
+ break;
+ case 0x01: /* AUX_CHAIN_IND */
+ if (!aux_pointer_present) {
+ /* Final fragment */
+ ad_reassembled = true;
+ }
+ if (!pinfo->fd->visited && adi_present) {
+
+ ae_had_key[0].length = 1;
+ ae_had_key[0].key = &interface_id;
+ ae_had_key[1].length = 1;
+ ae_had_key[1].key = &adapter_id;
+ ae_had_key[2].length = 1;
+ ae_had_key[2].key = &adi;
+ ae_had_key[3].length = 0;
+ ae_had_key[3].key = NULL;
+
+ ae_had_info = (ae_had_info_t *) wmem_tree_lookup32_array(adi_to_first_frame_tree, ae_had_key);
+
+ if (ae_had_info != NULL) {
+ if (!(flags & 0x01) && (ae_had_info->adv_addr.len > 0)) {
+ /* Copy Advertiser Address from AUX_ADV_IND if not present. */
+ copy_address_shallow(&pinfo->src, &ae_had_info->adv_addr);
+ }
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &connection_access_address;
- key[3].length = 1;
- key[3].key = &frame_number;
- key[4].length = 0;
- key[4].key = NULL;
+ fragment_add_seq(&btle_ea_host_advertising_data_reassembly_table,
+ tvb, offset, pinfo,
+ ae_had_info->first_frame_num, NULL,
+ ae_had_info->fragment_counter,
+ tvb_captured_length_remaining(tvb, offset) - 3,
+ !ad_reassembled, 0);
- connection_info = wmem_new0(wmem_file_scope(), connection_info_t);
- connection_info->interface_id = interface_id;
- connection_info->adapter_id = adapter_id;
- connection_info->access_address = connection_access_address;
+ ae_had_info->fragment_counter++;
+ if (ad_reassembled == true) {
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_btle, (uint32_t)(pinfo->curr_layer_num) << 8, ae_had_info);
+ }
+ }
+ }
+ ad_processed = true;
+ break;
+ default:
+ /* This field is 2 bits long, no special action needed */
+ break;
+ }
+ if (ad_processed) {
+ if (pinfo->fd->visited) {
+ /* Host Advertising Data fragment */
+ proto_tree_add_item(btle_tree, hf_extended_advertising_had_fragment, tvb, offset, tvb_captured_length_remaining(tvb, offset) - 3, ENC_NA);
+ if (ad_reassembled) {
+ fragment_head *fd_head = NULL;
+ tvbuff_t *assembled_tvb = NULL;
+
+ ae_had_info = (ae_had_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_btle, (uint32_t)(pinfo->curr_layer_num) << 8);
+ if (ae_had_info != NULL) {
+ col_append_str(pinfo->cinfo, COL_INFO, " (EA HAD Reassembled)");
+
+ if (!(flags & 0x01) && (ae_had_info->adv_addr.len > 0)) {
+ /* Copy Advertiser Address from AUX_ADV_IND if not present. */
+ copy_address_shallow(&pinfo->src, &ae_had_info->adv_addr);
+ }
- if (flags & 0x01)
- memcpy(connection_info->master_bd_addr, src_bd_addr, 6);
+ fd_head = fragment_get(&btle_ea_host_advertising_data_reassembly_table, pinfo, ae_had_info->first_frame_num, NULL);
+ assembled_tvb = process_reassembled_data(
+ tvb, offset, pinfo,
+ "Reassembled Host Advertising Data", fd_head,
+ &btle_ea_host_advertising_data_frag_items,
+ NULL, btle_tree);
- /* We don't create control procedure context trees for BTLE_DIR_UNKNOWN,
- * as the direction must be known for request/response matching. */
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs =
- wmem_tree_new(wmem_file_scope());
- connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs =
- wmem_tree_new(wmem_file_scope());
+ if (assembled_tvb) {
+ dissect_ad_eir(assembled_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, btle_tree);
+ }
+ }
+ }
+ else {
+ col_append_str(pinfo->cinfo, COL_INFO, " (EA HAD Fragment)");
+ }
+ offset += tvb_captured_length_remaining(tvb, offset) - 3;
+ }
+ }
+ }
- wmem_tree_insert32_array(connection_info_tree, key, connection_info);
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ /* Host Advertising Data */
+ next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
- connection_parameter_info->parameters_frame = pinfo->num;
+ if (btle_context && btle_context->aux_pdu_type_valid && btle_context->aux_pdu_type == 3) {
+ /* AUX_SCAN_RSP */
+ sub_item = proto_tree_add_item(btle_tree, hf_scan_response_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_scan_response_data);
- key[3].length = 1;
- key[3].key = &pinfo->num;
- wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
+ dissect_ad_eir(next_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, sub_tree);
}
-
- sf = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
-
- item = proto_tree_add_item_ret_uint(sync_info_tree, hf_extended_advertising_sync_info_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &sync_offset);
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_offset_units, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_offset_adjust, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- if (sync_offset > 0) {
- proto_item_append_text(item, " (%u usec)", sync_offset * ((sf & 0x2000) != 0 ? 300 : 30) + ((sf & 0x4000) != 0 ? 2457600 : 0));
- } else {
- proto_item_append_text(item, " Cannot be represented");
+ else {
+ dissect_ad_eir(next_tvb, interface_id, adapter_id, pinfo->num, src_bd_addr, pinfo, btle_tree);
}
- offset += 2;
-
- item = proto_tree_add_item_ret_uint(sync_info_tree, hf_extended_advertising_sync_info_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &interval);
- proto_item_append_text(item, " (%g msec)", interval * 1.25);
- offset += 2;
- sub_item = proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_channel_map, tvb, offset, 5, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ }
+ }
+ break;
+ }
+ default:
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ }
+ }
- call_dissector_with_data(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree, &reserved_offset);
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_sleep_clock_accuracy, tvb, offset + reserved_offset, 1, ENC_LITTLE_ENDIAN);
- offset += 5;
+ return offset;
+}
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
+static int
+dissect_btle_acl_or_iso(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ proto_tree *btle_tree,
+ const btle_context_t *btle_context,
+ uint32_t adapter_id,
+ uint32_t interface_id,
+ uint32_t access_address,
+ uint8_t btle_pdu_type)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ int offset = 0;
+ uint32_t length;
+ tvbuff_t *next_tvb;
+ connection_info_t *connection_info = NULL;
+ wmem_tree_t *wmem_tree;
+ wmem_tree_key_t key[5];
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_crc_init, tvb, offset, 3, ENC_LITTLE_ENDIAN);
- offset += 3;
+ uint32_t connection_access_address;
- proto_tree_add_item(sync_info_tree, hf_extended_advertising_sync_info_event_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_item *item;
+ unsigned item_value;
- acad_len -= 18;
- }
+ proto_item *data_header_item, *seq_item, *control_proc_item;
+ proto_tree *data_header_tree;
+ uint8_t oct;
+ uint8_t llid;
+ uint8_t control_opcode;
+ uint32_t direction = BTLE_DIR_UNKNOWN;
+ uint8_t other_direction = BTLE_DIR_UNKNOWN;
- if (flags & 0x40) {
- /* Tx Power */
- proto_tree_add_item(ext_header_tree, hf_extended_advertising_tx_power, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ bool add_l2cap_index = false;
+ bool retransmit = false;
+ bool cte_info_present = false;
- acad_len -= 1;
- }
+ /* Holds the last initiated control procedures for a given direction. */
+ control_proc_info_t *last_control_proc[3] = {0};
- if (acad_len > 0) {
- sub_item = proto_tree_add_item(ext_header_tree, hf_extended_advertising_header_acad, tvb, offset, acad_len, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_extended_advertising_acad);
-
- /* Additional Controller Advertising Data */
- next_tvb = tvb_new_subset_length(tvb, offset, acad_len);
- dissect_ad_eir(next_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, sub_tree);
+ if (btle_context) {
+ direction = btle_context->direction;
+ other_direction = (direction == BTLE_DIR_PERIPHERAL_CENTRAL) ? BTLE_DIR_CENTRAL_PERIPHERAL : BTLE_DIR_PERIPHERAL_CENTRAL;
+ }
- offset += acad_len;
+ btle_frame_info_t *btle_frame_info = NULL;
+ fragment_head *frag_btl2cap_msg = NULL;
+ btle_frame_info_t empty_btle_frame_info = {0, 0, 0, 0, 0};
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &access_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+
+ oct = tvb_get_uint8(tvb, offset);
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_info_tree, key);
+ if (wmem_tree) {
+ connection_info = (connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
+ if (connection_info) {
+ char *str_addr_src, *str_addr_dst;
+ /* Holds "Peripheral_0x" (13 chars) + access_address (as %08x, 8 chars) + NULL, which is the longest string */
+ int str_addr_len = 13 + 8 + 1;
+
+ str_addr_src = (char *) wmem_alloc(pinfo->pool, str_addr_len);
+ str_addr_dst = (char *) wmem_alloc(pinfo->pool, str_addr_len);
+
+ sub_item = proto_tree_add_ether(btle_tree, hf_central_bd_addr, tvb, 0, 0, connection_info->central_bd_addr);
+ proto_item_set_generated(sub_item);
+
+ sub_item = proto_tree_add_ether(btle_tree, hf_peripheral_bd_addr, tvb, 0, 0, connection_info->peripheral_bd_addr);
+ proto_item_set_generated(sub_item);
+
+ switch (direction) {
+ case BTLE_DIR_CENTRAL_PERIPHERAL:
+ snprintf(str_addr_src, str_addr_len, "Central_0x%08x", connection_info->access_address);
+ snprintf(str_addr_dst, str_addr_len, "Peripheral_0x%08x", connection_info->access_address);
+ set_address(&pinfo->dl_src, AT_ETHER, sizeof(connection_info->central_bd_addr), connection_info->central_bd_addr);
+ set_address(&pinfo->dl_dst, AT_ETHER, sizeof(connection_info->peripheral_bd_addr), connection_info->peripheral_bd_addr);
+ break;
+ case BTLE_DIR_PERIPHERAL_CENTRAL:
+ snprintf(str_addr_src, str_addr_len, "Peripheral_0x%08x", connection_info->access_address);
+ snprintf(str_addr_dst, str_addr_len, "Central_0x%08x", connection_info->access_address);
+ set_address(&pinfo->dl_src, AT_ETHER, sizeof(connection_info->peripheral_bd_addr), connection_info->peripheral_bd_addr);
+ set_address(&pinfo->dl_dst, AT_ETHER, sizeof(connection_info->central_bd_addr), connection_info->central_bd_addr);
+ break;
+ default:
+ /* BTLE_DIR_UNKNOWN */
+ snprintf(str_addr_src, str_addr_len, "Unknown_0x%08x", connection_info->access_address);
+ snprintf(str_addr_dst, str_addr_len, "Unknown_0x%08x", connection_info->access_address);
+ clear_address(&pinfo->dl_src);
+ clear_address(&pinfo->dl_dst);
+ break;
}
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- gboolean ad_processed = FALSE;
- if (btle_context && pdu_type == 0x07 && btle_context->aux_pdu_type_valid) {
- gboolean ad_reassembled = FALSE;
- ae_had_info_t *ae_had_info = NULL;
-
- switch (btle_context->aux_pdu_type) {
- case 0x00: /* AUX_ADV_IND */
- case 0x02: /* AUX_SYNC_IND */
- case 0x03: /* AUX_SCAN_RSP */
- if (aux_pointer_present) {
- /* Begining of new sequence of fragments */
- if (!pinfo->fd->visited && adi_present) {
- ae_had_info = wmem_new0(wmem_file_scope(), ae_had_info_t);
- ae_had_info->first_frame_num=pinfo->num;
-
- if (flags & 0x01) {
- /* Copy Advertiser Address to reassemble AUX_CHAIN_IND */
- copy_address_wmem(wmem_file_scope(), &ae_had_info->adv_addr, &pinfo->src);
- }
-
- ae_had_key[0].length = 1;
- ae_had_key[0].key = &interface_id;
- ae_had_key[1].length = 1;
- ae_had_key[1].key = &adapter_id;
- ae_had_key[2].length = 1;
- ae_had_key[2].key = &adi;
- ae_had_key[3].length = 0;
- ae_had_key[3].key = NULL;
-
- wmem_tree_insert32_array(adi_to_first_frame_tree, ae_had_key, ae_had_info);
-
- fragment_add_seq(&btle_ea_host_advertising_data_reassembly_table,
- tvb, offset, pinfo,
- ae_had_info->first_frame_num, NULL,
- ae_had_info->fragment_counter,
- tvb_captured_length_remaining(tvb, offset) - 3,
- !ad_reassembled, 0);
-
- ae_had_info->fragment_counter++;
- }
- ad_processed = TRUE;
- }
- break;
- case 0x01: /* AUX_CHAIN_IND */
- if (!aux_pointer_present) {
- /* Final fragment */
- ad_reassembled = TRUE;
- }
- if (!pinfo->fd->visited && adi_present) {
- ae_had_key[0].length = 1;
- ae_had_key[0].key = &interface_id;
- ae_had_key[1].length = 1;
- ae_had_key[1].key = &adapter_id;
- ae_had_key[2].length = 1;
- ae_had_key[2].key = &adi;
- ae_had_key[3].length = 0;
- ae_had_key[3].key = NULL;
-
- ae_had_info = (ae_had_info_t *) wmem_tree_lookup32_array(adi_to_first_frame_tree, ae_had_key);
-
- if (ae_had_info != NULL) {
- if (!(flags & 0x01) && (ae_had_info->adv_addr.len > 0)) {
- /* Copy Advertiser Address from AUX_ADV_IND if not present. */
- copy_address_shallow(&pinfo->src, &ae_had_info->adv_addr);
- }
-
- fragment_add_seq(&btle_ea_host_advertising_data_reassembly_table,
- tvb, offset, pinfo,
- ae_had_info->first_frame_num, NULL,
- ae_had_info->fragment_counter,
- tvb_captured_length_remaining(tvb, offset) - 3,
- !ad_reassembled, 0);
-
- ae_had_info->fragment_counter++;
- if (ad_reassembled == TRUE) {
- p_add_proto_data(wmem_file_scope(), pinfo, proto_btle, (guint32)(pinfo->curr_layer_num) << 8, ae_had_info);
- }
- }
- }
- ad_processed = TRUE;
- break;
- default:
- /* This field is 2 bits long, no special action needed */
- break;
- }
- if (ad_processed) {
- if (pinfo->fd->visited) {
- /* Host Advertising Data fragment */
- proto_tree_add_item(btle_tree, hf_extended_advertising_had_fragment, tvb, offset, tvb_captured_length_remaining(tvb, offset) - 3, ENC_NA);
- if (ad_reassembled) {
- fragment_head *fd_head = NULL;
- tvbuff_t *assembled_tvb = NULL;
-
- ae_had_info = (ae_had_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_btle, (guint32)(pinfo->curr_layer_num) << 8);
- if (ae_had_info != NULL) {
- col_append_str(pinfo->cinfo, COL_INFO, " (EA HAD Reassembled)");
-
- if (!(flags & 0x01) && (ae_had_info->adv_addr.len > 0)) {
- /* Copy Advertiser Address from AUX_ADV_IND if not present. */
- copy_address_shallow(&pinfo->src, &ae_had_info->adv_addr);
- }
-
- fd_head = fragment_get(&btle_ea_host_advertising_data_reassembly_table, pinfo, ae_had_info->first_frame_num, NULL);
- assembled_tvb = process_reassembled_data(
- tvb, offset, pinfo,
- "Reassembled Host Advertising Data", fd_head,
- &btle_ea_host_advertising_data_frag_items,
- NULL, btle_tree);
-
- if (assembled_tvb) {
- dissect_ad_eir(assembled_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, btle_tree);
- }
- }
- }
- else {
- col_append_str(pinfo->cinfo, COL_INFO, " (EA HAD Fragment)");
- }
- offset += tvb_captured_length_remaining(tvb, offset) - 3;
- }
- }
- }
-
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- /* Host Advertising Data */
- next_tvb = tvb_new_subset_length(tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
-
- if (btle_context && btle_context->aux_pdu_type_valid && btle_context->aux_pdu_type == 3) {
- /* AUX_SCAN_RSP */
- sub_item = proto_tree_add_item(btle_tree, hf_scan_response_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_scan_response_data);
+ set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(str_addr_src)+1, str_addr_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
- dissect_ad_eir(next_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, sub_tree);
- }
- else {
- dissect_ad_eir(next_tvb, interface_id, adapter_id, frame_number, src_bd_addr, pinfo, btle_tree);
- }
+ set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(str_addr_dst)+1, str_addr_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ /* Retrieve the last initiated control procedures. */
+ if (btle_pdu_type == BTLE_PDU_TYPE_DATA) {
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL] =
+ (control_proc_info_t *)wmem_tree_lookup32_le(connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs, pinfo->num);
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL] =
+ (control_proc_info_t *)wmem_tree_lookup32_le(connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs, pinfo->num);
+
+ if (!pinfo->fd->visited && btle_context && btle_context->event_counter_valid) {
+ control_proc_complete_if_instant_reached(pinfo->num,
+ btle_context->event_counter,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL]);
+ control_proc_complete_if_instant_reached(pinfo->num,
+ btle_context->event_counter,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL]);
}
}
- break;
- }
- default:
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
- }
- }
- } else if (btle_pdu_type == BTLE_PDU_TYPE_DATA || btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) {
- proto_item *data_header_item, *seq_item, *control_proc_item;
- proto_tree *data_header_tree;
- guint8 oct;
- guint8 llid;
- guint8 control_opcode;
- guint32 direction = BTLE_DIR_UNKNOWN;
- guint8 other_direction = BTLE_DIR_UNKNOWN;
-
- gboolean add_l2cap_index = FALSE;
- gboolean retransmit = FALSE;
- gboolean cte_info_present = FALSE;
-
- /* Holds the last initiated control procedures for a given direction. */
- control_proc_info_t *last_control_proc[3] = {0};
-
- if (btle_context) {
- direction = btle_context->direction;
- other_direction = (direction == BTLE_DIR_SLAVE_MASTER) ? BTLE_DIR_MASTER_SLAVE : BTLE_DIR_SLAVE_MASTER;
- }
- btle_frame_info_t *btle_frame_info = NULL;
- fragment_head *frag_btl2cap_msg = NULL;
- btle_frame_info_t empty_btle_frame_info = {0, 0, 0, 0, 0};
-
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &access_address;
- key[3].length = 0;
- key[3].key = NULL;
-
- oct = tvb_get_guint8(tvb, offset);
- wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_info_tree, key);
- if (wmem_tree) {
- connection_info = (connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
- if (connection_info) {
- gchar *str_addr_src, *str_addr_dst;
- /* Holds "unknown" + access_address + NULL, which is the longest string */
- int str_addr_len = 18 + 1;
-
- str_addr_src = (gchar *) wmem_alloc(pinfo->pool, str_addr_len);
- str_addr_dst = (gchar *) wmem_alloc(pinfo->pool, str_addr_len);
-
- sub_item = proto_tree_add_ether(btle_tree, hf_master_bd_addr, tvb, 0, 0, connection_info->master_bd_addr);
- proto_item_set_generated(sub_item);
-
- sub_item = proto_tree_add_ether(btle_tree, hf_slave_bd_addr, tvb, 0, 0, connection_info->slave_bd_addr);
- proto_item_set_generated(sub_item);
-
- switch (direction) {
- case BTLE_DIR_MASTER_SLAVE:
- snprintf(str_addr_src, str_addr_len, "Master_0x%08x", connection_info->access_address);
- snprintf(str_addr_dst, str_addr_len, "Slave_0x%08x", connection_info->access_address);
- set_address(&pinfo->dl_src, AT_ETHER, sizeof(connection_info->master_bd_addr), connection_info->master_bd_addr);
- set_address(&pinfo->dl_dst, AT_ETHER, sizeof(connection_info->slave_bd_addr), connection_info->slave_bd_addr);
- break;
- case BTLE_DIR_SLAVE_MASTER:
- snprintf(str_addr_src, str_addr_len, "Slave_0x%08x", connection_info->access_address);
- snprintf(str_addr_dst, str_addr_len, "Master_0x%08x", connection_info->access_address);
- set_address(&pinfo->dl_src, AT_ETHER, sizeof(connection_info->slave_bd_addr), connection_info->slave_bd_addr);
- set_address(&pinfo->dl_dst, AT_ETHER, sizeof(connection_info->master_bd_addr), connection_info->master_bd_addr);
- break;
- default:
- /* BTLE_DIR_UNKNOWN */
- snprintf(str_addr_src, str_addr_len, "Unknown_0x%08x", connection_info->access_address);
- snprintf(str_addr_dst, str_addr_len, "Unknown_0x%08x", connection_info->access_address);
- clear_address(&pinfo->dl_src);
- clear_address(&pinfo->dl_dst);
- break;
- }
-
- set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(str_addr_src)+1, str_addr_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
-
- set_address(&pinfo->net_dst, AT_STRINGZ, (int)strlen(str_addr_dst)+1, str_addr_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
-
- /* Retrieve the last initiated control procedures. */
- if (btle_pdu_type == BTLE_PDU_TYPE_DATA) {
- last_control_proc[BTLE_DIR_MASTER_SLAVE] =
- (control_proc_info_t *)wmem_tree_lookup32_le(connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs, pinfo->num);
- last_control_proc[BTLE_DIR_SLAVE_MASTER] =
- (control_proc_info_t *)wmem_tree_lookup32_le(connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs, pinfo->num);
-
- if (!pinfo->fd->visited && btle_context && btle_context->event_counter_valid) {
- control_proc_complete_if_instant_reached(pinfo->num,
- btle_context->event_counter,
- last_control_proc[BTLE_DIR_MASTER_SLAVE]);
- control_proc_complete_if_instant_reached(pinfo->num,
- btle_context->event_counter,
- last_control_proc[BTLE_DIR_SLAVE_MASTER]);
- }
- }
+ if (!pinfo->fd->visited) {
+ address *addr;
- if (!pinfo->fd->visited) {
- address *addr;
+ btle_frame_info = wmem_new0(wmem_file_scope(), btle_frame_info_t);
+ btle_frame_info->l2cap_index = connection_info->direction_info[direction].l2cap_index;
- btle_frame_info = wmem_new0(wmem_file_scope(), btle_frame_info_t);
- btle_frame_info->l2cap_index = connection_info->direction_info[direction].l2cap_index;
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_dst, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_dst.data, pinfo->dl_dst.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_DST, addr);
+ if (!connection_info->first_data_frame_seen) {
+ connection_info->first_data_frame_seen = 1;
+ btle_frame_info->retransmit = 0;
+ btle_frame_info->ack = 1;
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].prev_seq_num = 0;
+ connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].prev_seq_num = 1;
+ }
+ else {
+ uint8_t seq_num = !!(oct & 0x8), next_expected_seq_num = !!(oct & 0x4);
- if (!connection_info->first_data_frame_seen) {
- connection_info->first_data_frame_seen = 1;
+ if (seq_num != connection_info->direction_info[direction].prev_seq_num) {
+ /* SN is not equal to previous packet (in same direction) SN */
btle_frame_info->retransmit = 0;
- btle_frame_info->ack = 1;
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].prev_seq_num = 0;
- connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].prev_seq_num = 1;
+ } else {
+ btle_frame_info->retransmit = 1;
}
- else {
- guint8 seq_num = !!(oct & 0x8), next_expected_seq_num = !!(oct & 0x4);
+ connection_info->direction_info[direction].prev_seq_num = seq_num;
- if (seq_num != connection_info->direction_info[direction].prev_seq_num) {
- /* SN is not equal to previous packet (in same direction) SN */
- btle_frame_info->retransmit = 0;
- } else {
- btle_frame_info->retransmit = 1;
- }
- connection_info->direction_info[direction].prev_seq_num = seq_num;
-
- if (next_expected_seq_num != connection_info->direction_info[other_direction].prev_seq_num) {
- /* NESN is not equal to previous packet (in other direction) SN */
- btle_frame_info->ack = 1;
- } else {
- btle_frame_info->ack = 0;
- }
+ if (next_expected_seq_num != connection_info->direction_info[other_direction].prev_seq_num) {
+ /* NESN is not equal to previous packet (in other direction) SN */
+ btle_frame_info->ack = 1;
+ } else {
+ btle_frame_info->ack = 0;
}
- p_add_proto_data(wmem_file_scope(), pinfo, proto_btle, pinfo->curr_layer_num, btle_frame_info);
- }
- else {
- /* Not the first pass */
- btle_frame_info = (btle_frame_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_btle, pinfo->curr_layer_num);
}
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_btle, pinfo->curr_layer_num, btle_frame_info);
+ }
+ else {
+ /* Not the first pass */
+ btle_frame_info = (btle_frame_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_btle, pinfo->curr_layer_num);
}
}
+ }
- if (btle_frame_info == NULL) {
- btle_frame_info = &empty_btle_frame_info;
- }
+ if (btle_frame_info == NULL) {
+ btle_frame_info = &empty_btle_frame_info;
+ }
- if (btle_pdu_type == BTLE_PDU_TYPE_DATA) {
- cte_info_present = (oct & 0x20) != 0;
- }
+ if (btle_pdu_type == BTLE_PDU_TYPE_DATA) {
+ cte_info_present = (oct & 0x20) != 0;
+ }
- data_header_item = proto_tree_add_item(btle_tree, hf_data_header, tvb, offset, 2 + cte_info_present, ENC_NA);
- data_header_tree = proto_item_add_subtree(data_header_item, ett_data_header);
+ data_header_item = proto_tree_add_item(btle_tree, hf_data_header, tvb, offset, (cte_info_present) ? 3 : 2, ENC_NA);
+ data_header_tree = proto_item_add_subtree(data_header_item, ett_data_header);
- proto_tree_add_item(data_header_tree, (btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) ? hf_data_header_llid_connectediso :hf_data_header_llid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- seq_item = proto_tree_add_item(data_header_tree, hf_data_header_next_expected_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, (btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) ? hf_data_header_llid_connectediso :hf_data_header_llid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ seq_item = proto_tree_add_item(data_header_tree, hf_data_header_next_expected_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- if (direction != BTLE_DIR_UNKNOWN) {
- /* Unable to check valid NESN without direction */
- if (btle_frame_info->ack == 1) {
- proto_item_append_text(seq_item, " [ACK]");
- } else {
- proto_item_append_text(seq_item, " [Request retransmit]");
- expert_add_info(pinfo, seq_item, &ei_nack);
- }
+ if (direction != BTLE_DIR_UNKNOWN) {
+ /* Unable to check valid NESN without direction */
+ if (btle_frame_info->ack == 1) {
+ proto_item_append_text(seq_item, " [ACK]");
+ } else {
+ proto_item_append_text(seq_item, " [Request retransmit]");
+ expert_add_info(pinfo, seq_item, &ei_nack);
}
+ }
- seq_item = proto_tree_add_item(data_header_tree, hf_data_header_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ seq_item = proto_tree_add_item(data_header_tree, hf_data_header_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- if (direction != BTLE_DIR_UNKNOWN) {
- /* Unable to check valid SN or retransmission without direction */
- if (btle_frame_info->retransmit == 0) {
- proto_item_append_text(seq_item, " [OK]");
- }
- else {
- proto_item_append_text(seq_item, " [Retransmit]");
- if (btle_detect_retransmit) {
- expert_add_info(pinfo, seq_item, &ei_retransmit);
- retransmit = TRUE;
- }
+ if (direction != BTLE_DIR_UNKNOWN) {
+ /* Unable to check valid SN or retransmission without direction */
+ if (btle_frame_info->retransmit == 0) {
+ proto_item_append_text(seq_item, " [OK]");
+ }
+ else {
+ proto_item_append_text(seq_item, " [Retransmit]");
+ if (btle_detect_retransmit) {
+ expert_add_info(pinfo, seq_item, &ei_retransmit);
+ retransmit = true;
}
}
+ }
- llid = oct & 0x03;
- if (btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) {
- proto_tree_add_item(data_header_tree, hf_data_header_close_isochronous_event, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_null_pdu_indicator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_rfu_57, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- llid |= 0x04;
- } else {
- proto_tree_add_item(data_header_tree, hf_data_header_more_data, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_cte_info_present, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- }
- offset += 1;
+ llid = oct & 0x03;
+ if (btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) {
+ proto_tree_add_item(data_header_tree, hf_data_header_close_isochronous_event, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_null_pdu_indicator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_rfu_57, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ llid |= 0x04;
+ } else {
+ proto_tree_add_item(data_header_tree, hf_data_header_more_data, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_cte_info_present, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ }
+ offset += 1;
- proto_tree_add_item(data_header_tree, hf_data_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
- proto_item_set_hidden(item);
- offset += 1;
+ proto_tree_add_item(data_header_tree, hf_data_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ proto_item_set_hidden(item);
+ offset += 1;
- if (cte_info_present) {
- guint32 cte_time;
+ if (cte_info_present) {
+ uint32_t cte_time;
- sub_item = proto_tree_add_item(data_header_tree, hf_data_header_cte_info, tvb, offset, 1, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_data_header_cte_info);
+ sub_item = proto_tree_add_item(data_header_tree, hf_data_header_cte_info, tvb, offset, 1, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_data_header_cte_info);
- item = proto_tree_add_item_ret_uint(sub_tree, hf_data_header_cte_info_time, tvb, offset, 1, ENC_LITTLE_ENDIAN, &cte_time);
- proto_item_append_text(item, " (%u usec)", cte_time * 8);
- proto_tree_add_item(sub_tree, hf_data_header_cte_info_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(sub_tree, hf_data_header_cte_info_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
- }
+ item = proto_tree_add_item_ret_uint(sub_tree, hf_data_header_cte_info_time, tvb, offset, 1, ENC_LITTLE_ENDIAN, &cte_time);
+ proto_item_append_text(item, " (%u usec)", cte_time * 8);
+ proto_tree_add_item(sub_tree, hf_data_header_cte_info_rfu, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_data_header_cte_info_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
- switch (llid) {
- case 0x01: /* Continuation fragment of an L2CAP message, or an Empty PDU */
- if (length > 0) {
- tvbuff_t *new_tvb = NULL;
+ switch (llid) {
+ case 0x01: /* Continuation fragment of an L2CAP message, or an Empty PDU */
+ if (length > 0) {
+ tvbuff_t *new_tvb = NULL;
- pinfo->fragmented = TRUE;
- if (connection_info && !retransmit) {
- if (!pinfo->fd->visited) {
- if (connection_info->direction_info[direction].segmentation_started == 1) {
- if (connection_info->direction_info[direction].segment_len_rem >= length) {
- connection_info->direction_info[direction].segment_len_rem = connection_info->direction_info[direction].segment_len_rem - length;
- } else {
- /*
- * Missing fragment for previous L2CAP and fragment start for this.
- * Set more_fragments and increase l2cap_index to avoid reassembly.
- */
- btle_frame_info->more_fragments = 1;
- btle_frame_info->missing_start = 1;
- btle_frame_info->l2cap_index = l2cap_index;
- connection_info->direction_info[direction].l2cap_index = l2cap_index;
- connection_info->direction_info[direction].segmentation_started = 0;
- l2cap_index++;
- }
- if (connection_info->direction_info[direction].segment_len_rem > 0) {
- btle_frame_info->more_fragments = 1;
- }
- else {
- btle_frame_info->more_fragments = 0;
- connection_info->direction_info[direction].segmentation_started = 0;
- connection_info->direction_info[direction].segment_len_rem = 0;
- }
+ pinfo->fragmented = true;
+ if (connection_info && !retransmit) {
+ if (!pinfo->fd->visited) {
+ if (connection_info->direction_info[direction].segmentation_started == 1) {
+ if (connection_info->direction_info[direction].segment_len_rem >= length) {
+ connection_info->direction_info[direction].segment_len_rem = connection_info->direction_info[direction].segment_len_rem - length;
} else {
/*
- * Missing fragment start.
- * Set more_fragments and increase l2cap_index to avoid reassembly.
- */
+ * Missing fragment for previous L2CAP and fragment start for this.
+ * Set more_fragments and increase l2cap_index to avoid reassembly.
+ */
btle_frame_info->more_fragments = 1;
btle_frame_info->missing_start = 1;
btle_frame_info->l2cap_index = l2cap_index;
@@ -2920,19 +2987,110 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
connection_info->direction_info[direction].segmentation_started = 0;
l2cap_index++;
}
+ if (connection_info->direction_info[direction].segment_len_rem > 0) {
+ btle_frame_info->more_fragments = 1;
+ }
+ else {
+ btle_frame_info->more_fragments = 0;
+ connection_info->direction_info[direction].segmentation_started = 0;
+ connection_info->direction_info[direction].segment_len_rem = 0;
+ }
+ } else {
+ /*
+ * Missing fragment start.
+ * Set more_fragments and increase l2cap_index to avoid reassembly.
+ */
+ btle_frame_info->more_fragments = 1;
+ btle_frame_info->missing_start = 1;
+ btle_frame_info->l2cap_index = l2cap_index;
+ connection_info->direction_info[direction].l2cap_index = l2cap_index;
+ connection_info->direction_info[direction].segmentation_started = 0;
+ l2cap_index++;
}
+ }
+
+ add_l2cap_index = true;
+
+ frag_btl2cap_msg = fragment_add_seq_next(&btle_l2cap_msg_reassembly_table,
+ tvb, offset,
+ pinfo,
+ btle_frame_info->l2cap_index, /* uint32_t ID for fragments belonging together */
+ NULL, /* data* */
+ length, /* Fragment length */
+ btle_frame_info->more_fragments); /* More fragments */
+
+ new_tvb = process_reassembled_data(tvb, offset, pinfo,
+ "Reassembled L2CAP",
+ frag_btl2cap_msg,
+ &btle_l2cap_msg_frag_items,
+ NULL,
+ btle_tree);
+ }
- add_l2cap_index = TRUE;
+ if (new_tvb) {
+ bthci_acl_data_t *acl_data;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Data");
+
+ acl_data = wmem_new(pinfo->pool, bthci_acl_data_t);
+ acl_data->interface_id = interface_id;
+ acl_data->adapter_id = adapter_id;
+ acl_data->chandle = 0; /* No connection handle at this layer */
+ acl_data->remote_bd_addr_oui = 0;
+ acl_data->remote_bd_addr_id = 0;
+ acl_data->is_btle = true;
+ acl_data->is_btle_retransmit = retransmit;
+ acl_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
+ acl_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
+
+ next_tvb = tvb_new_subset_length(tvb, offset, length);
+ if (next_tvb) {
+ call_dissector_with_data(btl2cap_handle, new_tvb, pinfo, tree, acl_data);
+ }
+ offset += length;
+ }
+ else {
+ col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Fragment");
+ item = proto_tree_add_item(btle_tree, hf_l2cap_fragment, tvb, offset, length, ENC_NA);
+ if (btle_frame_info->missing_start) {
+ expert_add_info(pinfo, item, &ei_missing_fragment_start);
+ }
+ offset += length;
+ }
+ } else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Empty PDU");
+ }
+
+ break;
+ case 0x02: /* Start of an L2CAP message or a complete L2CAP message with no fragmentation */
+ if (length > 0) {
+ unsigned l2cap_len = tvb_get_letohs(tvb, offset);
+ if (l2cap_len + 4 > length) { /* L2CAP PDU Length excludes the 4 octets header */
+ pinfo->fragmented = true;
+ if (connection_info && !retransmit) {
+ if (!pinfo->fd->visited) {
+ connection_info->direction_info[direction].segmentation_started = 1;
+ /* The first two octets in the L2CAP PDU contain the length of the entire
+ * L2CAP PDU in octets, excluding the Length and CID fields(4 octets).
+ */
+ connection_info->direction_info[direction].segment_len_rem = l2cap_len + 4 - length;
+ connection_info->direction_info[direction].l2cap_index = l2cap_index;
+ btle_frame_info->more_fragments = 1;
+ btle_frame_info->l2cap_index = l2cap_index;
+ l2cap_index++;
+ }
+
+ add_l2cap_index = true;
frag_btl2cap_msg = fragment_add_seq_next(&btle_l2cap_msg_reassembly_table,
tvb, offset,
pinfo,
- btle_frame_info->l2cap_index, /* guint32 ID for fragments belonging together */
+ btle_frame_info->l2cap_index, /* uint32_t ID for fragments belonging together */
NULL, /* data* */
length, /* Fragment length */
btle_frame_info->more_fragments); /* More fragments */
- new_tvb = process_reassembled_data(tvb, offset, pinfo,
+ process_reassembled_data(tvb, offset, pinfo,
"Reassembled L2CAP",
frag_btl2cap_msg,
&btle_l2cap_msg_frag_items,
@@ -2940,1475 +3098,1506 @@ dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
btle_tree);
}
- if (new_tvb) {
- bthci_acl_data_t *acl_data;
-
- col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Data");
-
- acl_data = wmem_new(pinfo->pool, bthci_acl_data_t);
- acl_data->interface_id = interface_id;
- acl_data->adapter_id = adapter_id;
- acl_data->chandle = 0; /* No connection handle at this layer */
- acl_data->remote_bd_addr_oui = 0;
- acl_data->remote_bd_addr_id = 0;
- acl_data->is_btle = TRUE;
- acl_data->is_btle_retransmit = retransmit;
- acl_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
- acl_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
-
- next_tvb = tvb_new_subset_length(tvb, offset, length);
- if (next_tvb) {
- call_dissector_with_data(btl2cap_handle, new_tvb, pinfo, tree, acl_data);
- }
- offset += length;
- }
- else {
- col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Fragment");
- item = proto_tree_add_item(btle_tree, hf_l2cap_fragment, tvb, offset, length, ENC_NA);
- if (btle_frame_info->missing_start) {
- expert_add_info(pinfo, item, &ei_missing_fragment_start);
- }
- offset += length;
- }
+ col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Fragment Start");
+ proto_tree_add_item(btle_tree, hf_l2cap_fragment, tvb, offset, length, ENC_NA);
+ offset += length;
} else {
- col_set_str(pinfo->cinfo, COL_INFO, "Empty PDU");
- }
-
- break;
- case 0x02: /* Start of an L2CAP message or a complete L2CAP message with no fragmentation */
- if (length > 0) {
- guint l2cap_len = tvb_get_letohs(tvb, offset);
- if (l2cap_len + 4 > length) { /* L2CAP PDU Length excludes the 4 octets header */
- pinfo->fragmented = TRUE;
- if (connection_info && !retransmit) {
- if (!pinfo->fd->visited) {
- connection_info->direction_info[direction].segmentation_started = 1;
- /* The first two octets in the L2CAP PDU contain the length of the entire
- * L2CAP PDU in octets, excluding the Length and CID fields(4 octets).
- */
- connection_info->direction_info[direction].segment_len_rem = l2cap_len + 4 - length;
- connection_info->direction_info[direction].l2cap_index = l2cap_index;
- btle_frame_info->more_fragments = 1;
- btle_frame_info->l2cap_index = l2cap_index;
- l2cap_index++;
- }
-
- add_l2cap_index = TRUE;
-
- frag_btl2cap_msg = fragment_add_seq_next(&btle_l2cap_msg_reassembly_table,
- tvb, offset,
- pinfo,
- btle_frame_info->l2cap_index, /* guint32 ID for fragments belonging together */
- NULL, /* data* */
- length, /* Fragment length */
- btle_frame_info->more_fragments); /* More fragments */
-
- process_reassembled_data(tvb, offset, pinfo,
- "Reassembled L2CAP",
- frag_btl2cap_msg,
- &btle_l2cap_msg_frag_items,
- NULL,
- btle_tree);
- }
-
- col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Fragment Start");
- proto_tree_add_item(btle_tree, hf_l2cap_fragment, tvb, offset, length, ENC_NA);
- offset += length;
- } else {
- bthci_acl_data_t *acl_data;
- if (connection_info) {
- /* Add a L2CAP index for completeness */
- if (!pinfo->fd->visited) {
- btle_frame_info->l2cap_index = l2cap_index;
- l2cap_index++;
- }
-
- add_l2cap_index = TRUE;
+ bthci_acl_data_t *acl_data;
+ if (connection_info) {
+ /* Add a L2CAP index for completeness */
+ if (!pinfo->fd->visited) {
+ btle_frame_info->l2cap_index = l2cap_index;
+ l2cap_index++;
}
- col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Data");
-
- acl_data = wmem_new(pinfo->pool, bthci_acl_data_t);
- acl_data->interface_id = interface_id;
- acl_data->adapter_id = adapter_id;
- acl_data->chandle = 0; /* No connection handle at this layer */
- acl_data->remote_bd_addr_oui = 0;
- acl_data->remote_bd_addr_id = 0;
- acl_data->is_btle = TRUE;
- acl_data->is_btle_retransmit = retransmit;
- acl_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
- acl_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
-
- next_tvb = tvb_new_subset_length(tvb, offset, length);
- call_dissector_with_data(btl2cap_handle, next_tvb, pinfo, tree, acl_data);
- offset += length;
+ add_l2cap_index = true;
}
+
+ col_set_str(pinfo->cinfo, COL_INFO, "L2CAP Data");
+
+ acl_data = wmem_new(pinfo->pool, bthci_acl_data_t);
+ acl_data->interface_id = interface_id;
+ acl_data->adapter_id = adapter_id;
+ acl_data->chandle = 0; /* No connection handle at this layer */
+ acl_data->remote_bd_addr_oui = 0;
+ acl_data->remote_bd_addr_id = 0;
+ acl_data->is_btle = true;
+ acl_data->is_btle_retransmit = retransmit;
+ acl_data->adapter_disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
+ acl_data->disconnect_in_frame = &bluetooth_max_disconnect_in_frame;
+
+ next_tvb = tvb_new_subset_length(tvb, offset, length);
+ call_dissector_with_data(btl2cap_handle, next_tvb, pinfo, tree, acl_data);
+ offset += length;
}
- break;
- case 0x03: /* Control PDU */
- control_proc_item = proto_tree_add_item(btle_tree, hf_control_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- control_opcode = tvb_get_guint8(tvb, offset);
- offset += 1;
+ }
+ break;
+ case 0x03: /* Control PDU */
+ control_proc_item = proto_tree_add_item(btle_tree, hf_control_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ control_opcode = tvb_get_uint8(tvb, offset);
+ offset += 1;
- col_add_fstr(pinfo->cinfo, COL_INFO, "Control Opcode: %s",
- val_to_str_ext_const(control_opcode, &control_opcode_vals_ext, "Unknown"));
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Control Opcode: %s",
+ val_to_str_ext_const(control_opcode, &control_opcode_vals_ext, "Unknown"));
- switch (control_opcode) {
- case LL_CTRL_OPCODE_CONNECTION_UPDATE_IND:
- item = proto_tree_add_item_ret_uint(btle_tree, hf_control_window_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
- offset += 1;
+ switch (control_opcode) {
+ case LL_CTRL_OPCODE_CONNECTION_UPDATE_IND:
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_control_window_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 1;
- item = proto_tree_add_item_ret_uint(btle_tree, hf_control_window_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
- offset += 2;
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_control_window_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 2;
- item = proto_tree_add_item_ret_uint(btle_tree, hf_control_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%g msec)", item_value*1.25);
- offset += 2;
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_control_interval, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%g msec)", item_value*1.25);
+ offset += 2;
- proto_tree_add_item(btle_tree, hf_control_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(btle_tree, hf_control_latency, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- item = proto_tree_add_item_ret_uint(btle_tree, hf_control_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- proto_item_append_text(item, " (%u msec)", item_value*10);
- offset += 2;
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_control_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ proto_item_append_text(item, " (%u msec)", item_value*10);
+ offset += 2;
- proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- offset += 2;
+ proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ offset += 2;
- if (!pinfo->fd->visited) {
- if (connection_info) {
- connection_parameter_info_t *connection_parameter_info;
+ if (!pinfo->fd->visited) {
+ if (connection_info) {
+ connection_parameter_info_t *connection_parameter_info;
- connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
- connection_parameter_info->parameters_frame = pinfo->num;
+ connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
+ connection_parameter_info->parameters_frame = pinfo->num;
- if (btle_context && btle_context->event_counter_valid) {
- connection_info->connection_parameter_update_instant = item_value;
- connection_info->connection_parameter_update_info = connection_parameter_info;
- } else {
- /* We don't have event counter information needed to determine the exact time the new
- * connection parameters will be applied.
- * Instead just set it as active immediately.
- */
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &access_address;
- key[3].length = 1;
- key[3].key = &pinfo->num;
- key[4].length = 0;
- key[4].key = NULL;
- wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
- }
+ if (btle_context && btle_context->event_counter_valid) {
+ connection_info->connection_parameter_update_instant = item_value;
+ connection_info->connection_parameter_update_info = connection_parameter_info;
+ } else {
+ /* We don't have event counter information needed to determine the exact time the new
+ * connection parameters will be applied.
+ * Instead just set it as active immediately.
+ */
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &access_address;
+ key[3].length = 1;
+ key[3].key = &pinfo->num;
+ key[4].length = 0;
+ key[4].key = NULL;
+ wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
}
}
+ }
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_CONNECTION_UPDATE_IND can only be sent from master to slave.
- * It can either be sent as the first packet of the connection update procedure,
- * or as the last packet in the connection parameter request procedure. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 2)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- 1);
- } else {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
-
- if (proc_info) {
- if (btle_context && btle_context->event_counter_valid) {
- proc_info->instant = item_value;
- proc_info->frame_with_instant_value = pinfo->num;
- } else {
- /* Event counter is not available, assume the procedure completes now. */
- proc_info->last_frame = pinfo->num;
- }
- }
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_CONNECTION_UPDATE_IND can only be sent from central to peripheral.
+ * It can either be sent as the first packet of the connection update procedure,
+ * or as the last packet in the connection parameter request procedure. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 2)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ 1);
+ } else {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ if (proc_info) {
+ if (btle_context && btle_context->event_counter_valid) {
+ proc_info->instant = item_value;
+ proc_info->frame_with_instant_value = pinfo->num;
+ } else {
+ /* Event counter is not available, assume the procedure completes now. */
+ proc_info->last_frame = pinfo->num;
+ }
}
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
+
}
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_CHANNEL_MAP_IND:
- sub_item = proto_tree_add_item(btle_tree, hf_control_channel_map, tvb, offset, 5, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+ break;
+ case LL_CTRL_OPCODE_CHANNEL_MAP_IND:
+ sub_item = proto_tree_add_item(btle_tree, hf_control_channel_map, tvb, offset, 5, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+
+ call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
+ offset += 5;
- call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
- offset += 5;
+ proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ offset += 2;
- proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- offset += 2;
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_CHANNEL_MAP_REQ can only be sent from master to slave.
- * It can either be sent as the first packet of the channel map update procedure,
- * or as the last packet in the minimum number of used channels procedure. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- LL_CTRL_OPCODE_MIN_USED_CHANNELS_IND, 1)) {
- control_proc_add_frame_with_instant(tvb,
- pinfo,
- btle_tree,
- btle_context,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- 1,
- item_value);
- } else {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
-
- if (proc_info) {
- if (btle_context && btle_context->event_counter_valid) {
- proc_info->instant = item_value;
- proc_info->frame_with_instant_value = pinfo->num;
- } else {
- /* Event counter is not available, assume the procedure completes now. */
- proc_info->last_frame = pinfo->num;
- }
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_CHANNEL_MAP_REQ can only be sent from central to peripheral.
+ * It can either be sent as the first packet of the channel map update procedure,
+ * or as the last packet in the minimum number of used channels procedure. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ LL_CTRL_OPCODE_MIN_USED_CHANNELS_IND, 1)) {
+ control_proc_add_frame_with_instant(tvb,
+ pinfo,
+ btle_tree,
+ btle_context,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ 1,
+ item_value);
+ } else {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+
+ if (proc_info) {
+ if (btle_context && btle_context->event_counter_valid) {
+ proc_info->instant = item_value;
+ proc_info->frame_with_instant_value = pinfo->num;
+ } else {
+ /* Event counter is not available, assume the procedure completes now. */
+ proc_info->last_frame = pinfo->num;
}
}
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_TERMINATE_IND:
- proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ break;
+ case LL_CTRL_OPCODE_TERMINATE_IND:
+ proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- /* No need to mark procedure as started, as the procedure only consist
- * of one packet which may be sent at any time, */
+ /* No need to mark procedure as started, as the procedure only consist
+ * of one packet which may be sent at any time, */
- break;
- case LL_CTRL_OPCODE_ENC_REQ:
- proto_tree_add_item(btle_tree, hf_control_random_number, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- offset += 8;
-
- proto_tree_add_item(btle_tree, hf_control_encrypted_diversifier, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
-
- proto_tree_add_item(btle_tree, hf_control_master_session_key_diversifier, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- offset += 8;
-
- proto_tree_add_item(btle_tree, hf_control_master_session_initialization_vector, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_ENC_REQ can only be sent from master to slave. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ break;
+ case LL_CTRL_OPCODE_ENC_REQ:
+ proto_tree_add_item(btle_tree, hf_control_random_number, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
- break;
- case LL_CTRL_OPCODE_ENC_RSP:
- proto_tree_add_item(btle_tree, hf_control_slave_session_key_diversifier, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- offset += 8;
-
- proto_tree_add_item(btle_tree, hf_control_slave_session_initialization_vector, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_ENC_REQ can only be sent from slave to master. */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 1)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ proto_tree_add_item(btle_tree, hf_control_encrypted_diversifier, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- break;
- case LL_CTRL_OPCODE_START_ENC_REQ:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_START_ENC_REQ can only be sent from slave to master. */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 2)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ proto_tree_add_item(btle_tree, hf_control_central_session_key_diversifier, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
- break;
+ proto_tree_add_item(btle_tree, hf_control_central_session_initialization_vector, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- case LL_CTRL_OPCODE_START_ENC_RSP:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- /* This is either frame 4 or 5 of the procedure */
- if (direction == BTLE_DIR_MASTER_SLAVE &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 3)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 3);
- } else if (direction == BTLE_DIR_SLAVE_MASTER &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 4)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 4);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_ENC_REQ can only be sent from central to peripheral. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
+ break;
+ case LL_CTRL_OPCODE_ENC_RSP:
+ proto_tree_add_item(btle_tree, hf_control_peripheral_session_key_diversifier, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
- case LL_CTRL_OPCODE_UNKNOWN_RSP:
- proto_tree_add_item(btle_tree, hf_control_unknown_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
-
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- /* LL_UNKNOWN_RSP can only be sent as the second frame of a procedure. */
- if (last_control_proc[other_direction] &&
- control_proc_can_add_frame_even_if_complete(pinfo,
- last_control_proc[other_direction],
- last_control_proc[other_direction]->proc_opcode,
- 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ proto_tree_add_item(btle_tree, hf_control_peripheral_session_initialization_vector, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- break;
- case LL_CTRL_OPCODE_FEATURE_REQ:
- offset = dissect_feature_set(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_FEATURE_REQ can only be sent from master to slave. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_ENC_REQ can only be sent from peripheral to central. */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 1)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_FEATURE_RSP:
- offset = dissect_feature_set(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ break;
+ case LL_CTRL_OPCODE_START_ENC_REQ:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_START_ENC_REQ can only be sent from peripheral to central. */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_FEATURE_REQ, 1) ||
- control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_SLAVE_FEATURE_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 2)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
} else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_PAUSE_ENC_REQ:
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
- }
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_PAUSE_ENC_REQ can only be sent from master to slave. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ break;
- break;
- case LL_CTRL_OPCODE_PAUSE_ENC_RSP:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
-
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (direction == BTLE_DIR_SLAVE_MASTER &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_PAUSE_ENC_REQ, 1)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else if (direction == BTLE_DIR_MASTER_SLAVE &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_PAUSE_ENC_REQ, 2)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ case LL_CTRL_OPCODE_START_ENC_RSP:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ /* This is either frame 4 or 5 of the procedure */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 3)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 3);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 4)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 4);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_VERSION_IND:
- proto_tree_add_item(btle_tree, hf_control_version_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ break;
- proto_tree_add_item(btle_tree, hf_control_company_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ case LL_CTRL_OPCODE_UNKNOWN_RSP:
+ proto_tree_add_item(btle_tree, hf_control_unknown_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(btle_tree, hf_control_subversion_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ /* LL_UNKNOWN_RSP can only be sent as the second frame of a procedure. */
+ if (last_control_proc[other_direction] &&
+ control_proc_can_add_frame_even_if_complete(pinfo,
+ last_control_proc[other_direction],
+ last_control_proc[other_direction]->proc_opcode,
+ 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
+ }
+ }
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- /* The LL_VERSION_IND can be sent as a request or response.
- * We first check if it is a response. */
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_VERSION_IND, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
+ break;
+ case LL_CTRL_OPCODE_FEATURE_REQ:
+ offset = dissect_feature_set(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_FEATURE_REQ can only be sent from central to peripheral. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_REJECT_IND:
- proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
-
- /* LL_REJECT_IND my be sent as:
- * - A response to the LL_ENQ_REQ from the master
- * - After the LL_ENC_RSP from the slave */
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 2)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ break;
+ case LL_CTRL_OPCODE_FEATURE_RSP:
+ offset = dissect_feature_set(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_FEATURE_REQ, 1) ||
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_PERIPHERAL_FEATURE_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_SLAVE_FEATURE_REQ:
- offset = dissect_feature_set(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_SLAVE_FEATURE_REQ can only be sent from slave to master. */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ break;
+ case LL_CTRL_OPCODE_PAUSE_ENC_REQ:
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ }
+
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_PAUSE_ENC_REQ can only be sent from central to peripheral. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
+ }
- case LL_CTRL_OPCODE_CONNECTION_PARAM_REQ:
- offset = dissect_conn_param_req_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction != BTLE_DIR_UNKNOWN) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
+ break;
+ case LL_CTRL_OPCODE_PAUSE_ENC_RSP:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_PAUSE_ENC_REQ, 1)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_PAUSE_ENC_REQ, 2)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_CONNECTION_PARAM_RSP:
- offset = dissect_conn_param_req_rsp(tvb, btle_tree, offset);
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_CONNECTION_PARAM_RSP can only be sent from slave to master
- * as a response to a master initiated procedure */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ break;
+ case LL_CTRL_OPCODE_VERSION_IND:
+ proto_tree_add_item(btle_tree, hf_control_version_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(btle_tree, hf_control_company_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(btle_tree, hf_control_subversion_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ /* The LL_VERSION_IND can be sent as a request or response.
+ * We first check if it is a response. */
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_VERSION_IND, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
}
+ }
- break;
- case LL_CTRL_OPCODE_REJECT_EXT_IND:
- proto_tree_add_item(btle_tree, hf_control_reject_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
-
- proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
-
- /* LL_REJECT_EXT_IND my be sent as:
- * - A response to the LL_ENQ_REQ from the master
- * - After the LL_ENC_RSP from the slave
- * - As a response to LL_CONNECTION_PARAM_REQ
- * - As a response to LL_CONNECTION_PARAM_RSP
- * - As a response during the phy update procedure.
- * - As a response during the CTE request procedure.
- * - As a response to LL_CIS_REQ
- * - As a response to LL_CIS_RSP
- * - As a response to LL_POWER_CONTROL_REQ
- * - As a response to a LL_SUBRATE_REQ
- */
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (direction == BTLE_DIR_SLAVE_MASTER &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else if (direction == BTLE_DIR_SLAVE_MASTER &&
- control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_ENC_REQ, 2)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_PHY_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_CTE_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CIS_REQ, 1)) {
+ break;
+ case LL_CTRL_OPCODE_REJECT_IND:
+ proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* LL_REJECT_IND my be sent as:
+ * - A response to the LL_ENQ_REQ from the central
+ * - After the LL_ENC_RSP from the peripheral */
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 1)) {
control_proc_add_last_frame(tvb,
pinfo,
btle_tree,
control_opcode,
direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
1);
} else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CIS_REQ, 2)) {
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 2)) {
control_proc_add_last_frame(tvb,
pinfo,
btle_tree,
control_opcode,
direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
2);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_POWER_CONTROL_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- LL_CTRL_OPCODE_SUBRATE_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- 1);
} else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
- case LL_CTRL_OPCODE_PING_REQ:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ break;
+ case LL_CTRL_OPCODE_PERIPHERAL_FEATURE_REQ:
+ offset = dissect_feature_set(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_PERIPHERAL_FEATURE_REQ can only be sent from peripheral to central. */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
- break;
- case LL_CTRL_OPCODE_PING_RSP:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_PING_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
+ }
+ break;
- case LL_CTRL_OPCODE_LENGTH_REQ:
- dissect_length_req_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ case LL_CTRL_OPCODE_CONNECTION_PARAM_REQ:
+ offset = dissect_conn_param_req_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction != BTLE_DIR_UNKNOWN) {
control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
}
+ }
- break;
- case LL_CTRL_OPCODE_LENGTH_RSP:
- dissect_length_req_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ break;
+ case LL_CTRL_OPCODE_CONNECTION_PARAM_RSP:
+ offset = dissect_conn_param_req_rsp(tvb, btle_tree, offset);
+
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_CONNECTION_PARAM_RSP can only be sent from peripheral to central
+ * as a response to a central initiated procedure */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_LENGTH_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
} else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_PHY_REQ:
- dissect_phy_req_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
+ }
- break;
- case LL_CTRL_OPCODE_PHY_RSP:
- dissect_phy_req_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_PHY_RSP can only be sent from slave to master. */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_PHY_REQ, 1)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
+ break;
+ case LL_CTRL_OPCODE_REJECT_EXT_IND:
+ proto_tree_add_item(btle_tree, hf_control_reject_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- break;
- case LL_CTRL_OPCODE_PHY_UPDATE_IND:
- {
- guint64 phy_c_to_p, phy_p_to_c;
+ proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- item = proto_tree_add_bitmask_ret_uint64(btle_tree, tvb, offset, hf_control_m_to_s_phy, ett_m_to_s_phy, hfx_control_phys_update, ENC_NA, &phy_c_to_p);
- if (phy_c_to_p == 0) {
- proto_item_append_text(item, ", No change");
+ /* LL_REJECT_EXT_IND my be sent as:
+ * - A response to the LL_ENQ_REQ from the central
+ * - After the LL_ENC_RSP from the peripheral
+ * - As a response to LL_CONNECTION_PARAM_REQ
+ * - As a response to LL_CONNECTION_PARAM_RSP
+ * - As a response during the phy update procedure.
+ * - As a response during the CTE request procedure.
+ * - As a response to LL_CIS_REQ
+ * - As a response to LL_CIS_RSP
+ * - As a response to LL_POWER_CONTROL_REQ
+ * - As a response to a LL_SUBRATE_REQ
+ */
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL &&
+ control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_ENC_REQ, 2)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_CONNECTION_PARAM_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_PHY_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_CTE_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CIS_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CIS_REQ, 2)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_POWER_CONTROL_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ LL_CTRL_OPCODE_SUBRATE_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- offset += 1;
+ }
- item = proto_tree_add_bitmask_ret_uint64(btle_tree, tvb, offset, hf_control_s_to_m_phy, ett_s_to_m_phy, hfx_control_phys_update, ENC_NA, &phy_p_to_c);
- if (phy_p_to_c == 0) {
- proto_item_append_text(item, ", No change");
+ break;
+ case LL_CTRL_OPCODE_PING_REQ:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
+ break;
+ case LL_CTRL_OPCODE_PING_RSP:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_PING_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- offset += 1;
+ }
+ break;
+
+ case LL_CTRL_OPCODE_LENGTH_REQ:
+ dissect_length_req_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
- if (phy_c_to_p != 0 && phy_p_to_c != 0) {
- proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ break;
+ case LL_CTRL_OPCODE_LENGTH_RSP:
+ dissect_length_req_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_LENGTH_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
} else {
- /* If both the PHY_C_TO_P and PHY_P_TO_C fields are zero then there is no
- * Instant and the Instant field is reserved for future use.
- */
- proto_tree_add_item(btle_tree, hf_control_rfu_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- offset += 2;
-
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_PHY_UPDATE_IND can only be sent from master to slave. */
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_PHY_REQ, 2)) {
- control_proc_add_frame_with_instant(tvb,
- pinfo,
- btle_tree,
- btle_context,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2,
- item_value);
- } else if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- LL_CTRL_OPCODE_PHY_REQ, 1)){
- control_proc_add_frame_with_instant(tvb,
- pinfo,
- btle_tree,
- btle_context,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- 1,
- item_value);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
+ }
+ break;
+ case LL_CTRL_OPCODE_PHY_REQ:
+ dissect_phy_req_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
+
+ break;
+ case LL_CTRL_OPCODE_PHY_RSP:
+ dissect_phy_req_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_PHY_RSP can only be sent from peripheral to central. */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_PHY_REQ, 1)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ }
- break;
+ break;
+ case LL_CTRL_OPCODE_PHY_UPDATE_IND:
+ {
+ uint64_t phy_c_to_p, phy_p_to_c;
+
+ item = proto_tree_add_bitmask_ret_uint64(btle_tree, tvb, offset, hf_control_c_to_p_phy, ett_c_to_p_phy, hfx_control_phys_update, ENC_NA, &phy_c_to_p);
+ if (phy_c_to_p == 0) {
+ proto_item_append_text(item, ", No change");
}
- case LL_CTRL_OPCODE_MIN_USED_CHANNELS_IND:
- proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_phys, ett_phys, hfx_control_phys, ENC_NA);
- offset += 1;
+ offset += 1;
- proto_tree_add_item(btle_tree, hf_control_min_used_channels, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ item = proto_tree_add_bitmask_ret_uint64(btle_tree, tvb, offset, hf_control_p_to_c_phy, ett_p_to_c_phy, hfx_control_phys_update, ENC_NA, &phy_p_to_c);
+ if (phy_p_to_c == 0) {
+ proto_item_append_text(item, ", No change");
+ }
+ offset += 1;
- if (connection_info && !btle_frame_info->retransmit) {
- /* The LL_MIN_USED_CHANNELS_IND can only be sent from slave to master. */
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ if (phy_c_to_p != 0 && phy_p_to_c != 0) {
+ proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ } else {
+ /* If both the PHY_C_TO_P and PHY_P_TO_C fields are zero then there is no
+ * Instant and the Instant field is reserved for future use.
+ */
+ proto_tree_add_item(btle_tree, hf_control_rfu_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ }
+ offset += 2;
- /* Procedure completes in the same frame. */
- if (proc_info) {
- proc_info->last_frame = pinfo->num;
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_CTE_REQ:
- proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_phys, ett_cte, hfx_control_cte, ENC_NA);
- offset += 1;
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
- break;
- case LL_CTRL_OPCODE_CTE_RSP:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_PHY_UPDATE_IND can only be sent from central to peripheral. */
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_CTE_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_PHY_REQ, 2)) {
+ control_proc_add_frame_with_instant(tvb,
+ pinfo,
+ btle_tree,
+ btle_context,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2,
+ item_value);
+ } else if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ LL_CTRL_OPCODE_PHY_REQ, 1)){
+ control_proc_add_frame_with_instant(tvb,
+ pinfo,
+ btle_tree,
+ btle_context,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ 1,
+ item_value);
} else {
expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_PERIODIC_SYNC_IND:
- offset = dissect_periodic_sync_ind(tvb, btle_tree, offset, pinfo, interface_id, adapter_id);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ }
+
+ break;
+ }
+ case LL_CTRL_OPCODE_MIN_USED_CHANNELS_IND:
+ proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_phys, ett_phys, hfx_control_phys, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_item(btle_tree, hf_control_min_used_channels, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ if (connection_info && !btle_frame_info->retransmit) {
+ /* The LL_MIN_USED_CHANNELS_IND can only be sent from peripheral to central. */
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
control_proc_info_t *proc_info;
proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
/* Procedure completes in the same frame. */
if (proc_info) {
proc_info->last_frame = pinfo->num;
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_CLOCK_ACCURACY_REQ:
- proto_tree_add_item(btle_tree, hf_control_sleep_clock_accuracy, tvb, offset, 1, ENC_NA);
- offset += 1;
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ }
+ break;
+ case LL_CTRL_OPCODE_CTE_REQ:
+ proto_tree_add_bitmask(btle_tree, tvb, offset, hf_control_phys, ett_cte, hfx_control_cte, ENC_NA);
+ offset += 1;
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
+ break;
+ case LL_CTRL_OPCODE_CTE_RSP:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_CTE_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_CLOCK_ACCURACY_RSP:
- proto_tree_add_item(btle_tree, hf_control_sleep_clock_accuracy, tvb, offset, 1, ENC_NA);
- offset += 1;
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_CLOCK_ACCURACY_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ }
+ break;
+ case LL_CTRL_OPCODE_PERIODIC_SYNC_IND:
+ offset = dissect_periodic_sync_ind(tvb, btle_tree, offset, pinfo, interface_id, adapter_id);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+
+ /* Procedure completes in the same frame. */
+ if (proc_info) {
+ proc_info->last_frame = pinfo->num;
}
- break;
- case LL_CTRL_OPCODE_CIS_REQ:
- offset = dissect_cis_req(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- control_opcode);
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ }
+ break;
+ case LL_CTRL_OPCODE_CLOCK_ACCURACY_REQ:
+ proto_tree_add_item(btle_tree, hf_control_sleep_clock_accuracy, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
+ break;
+ case LL_CTRL_OPCODE_CLOCK_ACCURACY_RSP:
+ proto_tree_add_item(btle_tree, hf_control_sleep_clock_accuracy, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_CLOCK_ACCURACY_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_CIS_RSP:
- offset = dissect_cis_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CIS_REQ, 1)) {
- control_proc_add_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ }
+ break;
+ case LL_CTRL_OPCODE_CIS_REQ:
+ offset = dissect_cis_req(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ control_opcode);
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_CIS_IND:
- if (!pinfo->fd->visited) {
- connection_info_t *nconnection_info;
- connection_parameter_info_t *connection_parameter_info;
+ }
+ break;
+ case LL_CTRL_OPCODE_CIS_RSP:
+ offset = dissect_cis_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CIS_REQ, 1)) {
+ control_proc_add_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
+ }
+ }
+ break;
+ case LL_CTRL_OPCODE_CIS_IND:
+ if (!pinfo->fd->visited) {
+ connection_info_t *nconnection_info;
+ connection_parameter_info_t *connection_parameter_info;
- connection_access_address = tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN);
-
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &connection_access_address;
- key[3].length = 1;
- key[3].key = &frame_number;
- key[4].length = 0;
- key[4].key = NULL;
-
- nconnection_info = wmem_new0(wmem_file_scope(), connection_info_t);
- nconnection_info->interface_id = interface_id;
- nconnection_info->adapter_id = adapter_id;
- nconnection_info->access_address = connection_access_address;
-
- if (connection_info) {
- memcpy(nconnection_info->master_bd_addr, connection_info->master_bd_addr, 6);
- memcpy(nconnection_info->slave_bd_addr, connection_info->slave_bd_addr, 6);
- }
+ connection_access_address = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
- /* We don't create control procedure context trees for BTLE_DIR_UNKNOWN,
- * as the direction must be known for request/response matching. */
- nconnection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs =
- wmem_tree_new(wmem_file_scope());
- nconnection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs =
- wmem_tree_new(wmem_file_scope());
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &connection_access_address;
+ key[3].length = 1;
+ key[3].key = &pinfo->num;
+ key[4].length = 0;
+ key[4].key = NULL;
- wmem_tree_insert32_array(connection_info_tree, key, nconnection_info);
+ nconnection_info = wmem_new0(wmem_file_scope(), connection_info_t);
+ nconnection_info->interface_id = interface_id;
+ nconnection_info->adapter_id = adapter_id;
+ nconnection_info->access_address = connection_access_address;
- connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
- connection_parameter_info->parameters_frame = pinfo->num;
+ if (connection_info) {
+ memcpy(nconnection_info->central_bd_addr, connection_info->central_bd_addr, 6);
+ memcpy(nconnection_info->peripheral_bd_addr, connection_info->peripheral_bd_addr, 6);
+ }
+
+ /* We don't create control procedure context trees for BTLE_DIR_UNKNOWN,
+ * as the direction must be known for request/response matching. */
+ nconnection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
+ nconnection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs =
+ wmem_tree_new(wmem_file_scope());
+
+ wmem_tree_insert32_array(connection_info_tree, key, nconnection_info);
+
+ connection_parameter_info = wmem_new0(wmem_file_scope(), connection_parameter_info_t);
+ connection_parameter_info->parameters_frame = pinfo->num;
- key[3].length = 1;
- key[3].key = &pinfo->num;
- wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
+ key[3].length = 1;
+ key[3].key = &pinfo->num;
+ wmem_tree_insert32_array(connection_parameter_info_tree, key, connection_parameter_info);
+ }
+ offset = dissect_cis_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ LL_CTRL_OPCODE_CIS_REQ, 2)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ 2);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- offset = dissect_cis_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- LL_CTRL_OPCODE_CIS_REQ, 2)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- 2);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
+ }
+ break;
+ case LL_CTRL_OPCODE_CIS_TERMINATE_IND:
+ offset = dissect_cis_terminate_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+
+ /* Procedure completes in the same frame. */
+ if (proc_info) {
+ proc_info->last_frame = pinfo->num;
}
- break;
- case LL_CTRL_OPCODE_CIS_TERMINATE_IND:
- offset = dissect_cis_terminate_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ }
+ break;
+ case LL_CTRL_OPCODE_POWER_CONTROL_REQ:
+ offset = dissect_power_control_req(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+ }
+ break;
+ case LL_CTRL_OPCODE_POWER_CONTROL_RSP:
+ offset = dissect_power_control_rsp(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[other_direction],
+ LL_CTRL_OPCODE_POWER_CONTROL_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[other_direction],
+ last_control_proc[direction],
+ 1);
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
+ }
+ }
+ break;
+ case LL_CTRL_OPCODE_POWER_CHANGE_IND:
+ offset = dissect_power_control_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+
+ /* Procedure completes in the same frame. */
+ if (proc_info) {
+ proc_info->last_frame = pinfo->num;
+ }
+ }
+ break;
+ case LL_CTRL_OPCODE_SUBRATE_REQ:
+ offset = dissect_subrate_req(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ control_opcode);
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
+ }
+ }
+ break;
+ case LL_CTRL_OPCODE_SUBRATE_IND:
+ offset = dissect_subrate_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (control_proc_can_add_frame(pinfo,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ LL_CTRL_OPCODE_SUBRATE_REQ, 1)) {
+ control_proc_add_last_frame(tvb,
+ pinfo,
+ btle_tree,
+ control_opcode,
+ direction,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ 1);
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
control_proc_info_t *proc_info;
proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ control_opcode);
/* Procedure completes in the same frame. */
if (proc_info) {
proc_info->last_frame = pinfo->num;
}
+ } else {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_POWER_CONTROL_REQ:
- offset = dissect_power_control_req(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
- }
- break;
- case LL_CTRL_OPCODE_POWER_CONTROL_RSP:
- offset = dissect_power_control_rsp(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[other_direction],
- LL_CTRL_OPCODE_POWER_CONTROL_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[other_direction],
- last_control_proc[direction],
- 1);
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_POWER_CHANGE_IND:
- offset = dissect_power_control_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ }
+ break;
+ case LL_CTRL_OPCODE_CHANNEL_REPORTING_IND:
+ offset = dissect_channel_reporting_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
control_proc_info_t *proc_info;
proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ connection_info->direction_info[BTLE_DIR_CENTRAL_PERIPHERAL].control_procs,
+ last_control_proc[BTLE_DIR_PERIPHERAL_CENTRAL],
+ control_opcode);
/* Procedure completes in the same frame. */
if (proc_info) {
proc_info->last_frame = pinfo->num;
}
+ } else if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- case LL_CTRL_OPCODE_SUBRATE_REQ:
- offset = dissect_subrate_req(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- control_opcode);
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_SUBRATE_IND:
- offset = dissect_subrate_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (control_proc_can_add_frame(pinfo,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- LL_CTRL_OPCODE_SUBRATE_REQ, 1)) {
- control_proc_add_last_frame(tvb,
- pinfo,
- btle_tree,
- control_opcode,
- direction,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- 1);
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- control_opcode);
-
- /* Procedure completes in the same frame. */
- if (proc_info) {
- proc_info->last_frame = pinfo->num;
- }
- } else {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_CHANNEL_REPORTING_IND:
- offset = dissect_channel_reporting_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction == BTLE_DIR_MASTER_SLAVE) {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_MASTER_SLAVE].control_procs,
- last_control_proc[BTLE_DIR_SLAVE_MASTER],
- control_opcode);
-
- /* Procedure completes in the same frame. */
- if (proc_info) {
- proc_info->last_frame = pinfo->num;
- }
- } else if (direction == BTLE_DIR_SLAVE_MASTER) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_CHANNEL_STATUS_IND:
- offset = dissect_channel_status_ind(tvb, btle_tree, offset);
- if (connection_info && !btle_frame_info->retransmit) {
- if (direction == BTLE_DIR_SLAVE_MASTER) {
- control_proc_info_t *proc_info;
- proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[BTLE_DIR_SLAVE_MASTER].control_procs,
- last_control_proc[BTLE_DIR_MASTER_SLAVE],
- control_opcode);
-
- /* Procedure completes in the same frame. */
- if (proc_info) {
- proc_info->last_frame = pinfo->num;
- }
- } else if (direction == BTLE_DIR_MASTER_SLAVE) {
- expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
- }
- }
- break;
- case LL_CTRL_OPCODE_PERIODIC_SYNC_WR_IND:
- offset = dissect_periodic_sync_wr_ind(tvb, btle_tree, offset, pinfo, interface_id, adapter_id);
- if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ }
+ break;
+ case LL_CTRL_OPCODE_CHANNEL_STATUS_IND:
+ offset = dissect_channel_status_ind(tvb, btle_tree, offset);
+ if (connection_info && !btle_frame_info->retransmit) {
+ if (direction == BTLE_DIR_PERIPHERAL_CENTRAL) {
control_proc_info_t *proc_info;
proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
- connection_info->direction_info[direction].control_procs,
- last_control_proc[other_direction],
- control_opcode);
+ connection_info->direction_info[BTLE_DIR_PERIPHERAL_CENTRAL].control_procs,
+ last_control_proc[BTLE_DIR_CENTRAL_PERIPHERAL],
+ control_opcode);
/* Procedure completes in the same frame. */
if (proc_info) {
proc_info->last_frame = pinfo->num;
}
+ } else if (direction == BTLE_DIR_CENTRAL_PERIPHERAL) {
+ expert_add_info(pinfo, control_proc_item, &ei_control_proc_wrong_seq);
}
- break;
- default:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- break;
}
-
break;
-
- case 0x04: /* Unframed CIS Data PDU; end fragment of an SDU or a complete SDU */
- case 0x05: /* Unframed CIS Data PDU; start or continuation fragment of an SDU */
- case 0x06: /* Framed CIS Data PDU; one or more segments of an SDU */
- proto_tree_add_item(btle_tree, hf_isochronous_data, tvb, offset, length, ENC_NA);
- offset += length;
+ case LL_CTRL_OPCODE_PERIODIC_SYNC_WR_IND:
+ offset = dissect_periodic_sync_wr_ind(tvb, btle_tree, offset, pinfo, interface_id, adapter_id);
+ if (connection_info && !btle_frame_info->retransmit && direction != BTLE_DIR_UNKNOWN) {
+ control_proc_info_t *proc_info;
+ proc_info = control_proc_start(tvb, pinfo, btle_tree, control_proc_item,
+ connection_info->direction_info[direction].control_procs,
+ last_control_proc[other_direction],
+ control_opcode);
+
+ /* Procedure completes in the same frame. */
+ if (proc_info) {
+ proc_info->last_frame = pinfo->num;
+ }
+ }
break;
-
default:
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
- }
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ break;
}
- if (add_l2cap_index) {
- item = proto_tree_add_uint(btle_tree, hf_l2cap_index, tvb, 0, 0, btle_frame_info->l2cap_index);
- proto_item_set_generated(item);
- }
+ break;
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &access_address;
- key[3].length = 0;
- key[3].key = NULL;
- wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_parameter_info_tree, key);
- if (wmem_tree) {
- connection_parameter_info_t *connection_parameter_info;
+ case 0x04: /* Unframed CIS Data PDU; end fragment of an SDU or a complete SDU */
+ case 0x05: /* Unframed CIS Data PDU; start or continuation fragment of an SDU */
+ case 0x06: /* Framed CIS Data PDU; one or more segments of an SDU */
+ proto_tree_add_item(btle_tree, hf_isochronous_data, tvb, offset, length, ENC_NA);
+ offset += length;
+ break;
- if (connection_info && connection_info->connection_parameter_update_info != NULL &&
- btle_context && btle_context->event_counter_valid) {
- if ( ((gint16)btle_context->event_counter - connection_info->connection_parameter_update_instant) >= 0) {
- wmem_tree_insert32(wmem_tree, pinfo->num, connection_info->connection_parameter_update_info);
- connection_info->connection_parameter_update_info = NULL;
- }
- }
+ default:
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ }
+ }
+
+ if (add_l2cap_index) {
+ item = proto_tree_add_uint(btle_tree, hf_l2cap_index, tvb, 0, 0, btle_frame_info->l2cap_index);
+ proto_item_set_generated(item);
+ }
- connection_parameter_info = (connection_parameter_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
- if (connection_parameter_info) {
- item = proto_tree_add_uint(btle_tree, hf_connection_parameters_in, tvb, 0, 0, connection_parameter_info->parameters_frame);
- proto_item_set_generated(item);
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &access_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(connection_parameter_info_tree, key);
+ if (wmem_tree) {
+ connection_parameter_info_t *connection_parameter_info;
+
+ if (connection_info && connection_info->connection_parameter_update_info != NULL &&
+ btle_context && btle_context->event_counter_valid) {
+ if ( ((int16_t)btle_context->event_counter - connection_info->connection_parameter_update_instant) >= 0) {
+ wmem_tree_insert32(wmem_tree, pinfo->num, connection_info->connection_parameter_update_info);
+ connection_info->connection_parameter_update_info = NULL;
}
}
- if ((crc_status == CRC_INDETERMINATE) &&
- btle_context && btle_context->connection_info_valid) {
- /* the surrounding context has provided CRCInit */
- crc_init = btle_context->connection_info.CRCInit;
- crc_status = CRC_CAN_BE_CALCULATED;
+ connection_parameter_info = (connection_parameter_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
+ if (connection_parameter_info) {
+ item = proto_tree_add_uint(btle_tree, hf_connection_parameters_in, tvb, 0, 0, connection_parameter_info->parameters_frame);
+ proto_item_set_generated(item);
}
- } else if (btle_pdu_type == BTLE_PDU_TYPE_BROADCASTISO) {
- broadcastiso_connection_info_t *broadcastiso_connection_info = NULL;
- guint32 seed_access_address = access_address & 0x0041ffff;
- proto_item *data_header_item;
- proto_tree *data_header_tree;
- guint8 llid;
- guint8 control_opcode;
-
- key[0].length = 1;
- key[0].key = &interface_id;
- key[1].length = 1;
- key[1].key = &adapter_id;
- key[2].length = 1;
- key[2].key = &seed_access_address;
- key[3].length = 0;
- key[3].key = NULL;
-
- wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(broadcastiso_connection_info_tree, key);
- if (wmem_tree) {
- broadcastiso_connection_info = (broadcastiso_connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
- if (broadcastiso_connection_info) {
- gchar *str_addr_src;
- /* Holds "Master" + access_address + NULL, which is the longest string */
- int str_addr_len = 17 + 1;
-
- str_addr_src = (gchar *) wmem_alloc(pinfo->pool, str_addr_len);
+ }
- sub_item = proto_tree_add_ether(btle_tree, hf_master_bd_addr, tvb, 0, 0, broadcastiso_connection_info->master_bd_addr);
- proto_item_set_generated(sub_item);
+ return offset;
+}
- snprintf(str_addr_src, str_addr_len, "Master_0x%08x", broadcastiso_connection_info->access_address);
- set_address(&pinfo->dl_src, AT_ETHER, sizeof(broadcastiso_connection_info->master_bd_addr), broadcastiso_connection_info->master_bd_addr);
- clear_address(&pinfo->dl_dst);
+static int
+dissect_btle_broadcast_iso(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *btle_tree,
+ uint32_t adapter_id,
+ uint32_t interface_id,
+ uint32_t access_address)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ int offset = 0;
+ uint32_t length;
+ static const uint8_t broadcast_addr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ wmem_tree_t *wmem_tree;
+ wmem_tree_key_t key[5];
- set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(str_addr_src)+1, str_addr_src);
- copy_address_shallow(&pinfo->src, &pinfo->net_src);
+ proto_item *item;
+ unsigned item_value;
+
+ broadcastiso_connection_info_t *broadcastiso_connection_info = NULL;
+ uint32_t seed_access_address = access_address & 0x0041ffff;
+ proto_item *data_header_item;
+ proto_tree *data_header_tree;
+ uint8_t llid;
+ uint8_t control_opcode;
+
+ key[0].length = 1;
+ key[0].key = &interface_id;
+ key[1].length = 1;
+ key[1].key = &adapter_id;
+ key[2].length = 1;
+ key[2].key = &seed_access_address;
+ key[3].length = 0;
+ key[3].key = NULL;
+
+ wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(broadcastiso_connection_info_tree, key);
+ if (wmem_tree) {
+ broadcastiso_connection_info = (broadcastiso_connection_info_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->num);
+ if (broadcastiso_connection_info) {
+ char *str_addr_src;
+ /* Holds "Central" + access_address + NULL, which is the longest string */
+ int str_addr_len = 17 + 1;
+
+ str_addr_src = (char *) wmem_alloc(pinfo->pool, str_addr_len);
+
+ sub_item = proto_tree_add_ether(btle_tree, hf_central_bd_addr, tvb, 0, 0, broadcastiso_connection_info->central_bd_addr);
+ proto_item_set_generated(sub_item);
+
+ snprintf(str_addr_src, str_addr_len, "Central_0x%08x", broadcastiso_connection_info->access_address);
+ set_address(&pinfo->dl_src, AT_ETHER, sizeof(broadcastiso_connection_info->central_bd_addr), broadcastiso_connection_info->central_bd_addr);
+ clear_address(&pinfo->dl_dst);
+
+ set_address(&pinfo->net_src, AT_STRINGZ, (int)strlen(str_addr_src)+1, str_addr_src);
+ copy_address_shallow(&pinfo->src, &pinfo->net_src);
- if (!pinfo->fd->visited) {
- address *addr;
+ if (!pinfo->fd->visited) {
+ address *addr;
- addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
- addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
- p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
- }
+ addr = (address *) wmem_memdup(wmem_file_scope(), &pinfo->dl_src, sizeof(address));
+ addr->data = wmem_memdup(wmem_file_scope(), pinfo->dl_src.data, pinfo->dl_src.len);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_bluetooth, BLUETOOTH_DATA_SRC, addr);
}
}
+ }
- set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
- copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
- copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
+ set_address(&pinfo->net_dst, AT_ETHER, 6, broadcast_addr);
+ copy_address_shallow(&pinfo->dl_dst, &pinfo->net_dst);
+ copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
- data_header_item = proto_tree_add_item(btle_tree, hf_data_header, tvb, offset, 2, ENC_NA);
- data_header_tree = proto_item_add_subtree(data_header_item, ett_data_header);
+ data_header_item = proto_tree_add_item(btle_tree, hf_data_header, tvb, offset, 2, ENC_NA);
+ data_header_tree = proto_item_add_subtree(data_header_item, ett_data_header);
- proto_tree_add_item(data_header_tree, hf_data_header_llid_broadcastiso, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- llid = tvb_get_guint8(tvb, offset) & 0x03;
- proto_tree_add_item(data_header_tree, hf_data_header_control_subevent_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_control_subevent_transmission_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(data_header_tree, hf_data_header_rfu_67, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
+ proto_tree_add_item(data_header_tree, hf_data_header_llid_broadcastiso, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ llid = tvb_get_uint8(tvb, offset) & 0x03;
+ proto_tree_add_item(data_header_tree, hf_data_header_control_subevent_sequence_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_control_subevent_transmission_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(data_header_tree, hf_data_header_rfu_67, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(data_header_tree, hf_data_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ proto_item_set_hidden(item);
+ offset += 1;
- proto_tree_add_item(data_header_tree, hf_data_header_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- item = proto_tree_add_item_ret_uint(btle_tree, hf_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
- proto_item_set_hidden(item);
+ switch (llid) {
+ case 0x00: /* Unframed BIS Data PDU; end fragment of an SDU or a complete SDU */
+ case 0x01: /* Unframed BIS Data PDU; start or continuation fragment of an SDU */
+ case 0x02: /* Framed BIS Data PDU; one or more segments of an SDU */
+ proto_tree_add_item(btle_tree, hf_isochronous_data, tvb, offset, length, ENC_NA);
+ offset += length;
+ break;
+
+ case 0x03: /* BIG Control PDU */
+ proto_tree_add_item(btle_tree, hf_big_control_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ control_opcode = tvb_get_uint8(tvb, offset);
offset += 1;
- switch (llid) {
- case 0x00: /* Unframed BIS Data PDU; end fragment of an SDU or a complete SDU */
- case 0x01: /* Unframed BIS Data PDU; start or continuation fragment of an SDU */
- case 0x02: /* Framed BIS Data PDU; one or more segments of an SDU */
- proto_tree_add_item(btle_tree, hf_isochronous_data, tvb, offset, length, ENC_NA);
- offset += length;
+ col_add_fstr(pinfo->cinfo, COL_INFO, "BIG Control Opcode: %s",
+ val_to_str_ext_const(control_opcode, &big_control_opcode_vals_ext, "Unknown"));
+
+ switch (control_opcode) {
+ case 0x00: /* BIG_CHANNEL_MAP_IND */
+ sub_item = proto_tree_add_item(btle_tree, hf_control_channel_map, tvb, offset, 5, ENC_NA);
+ sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+
+ call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
+ offset += 5;
+
+ proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ offset += 2;
break;
- case 0x03: /* BIG Control PDU */
- proto_tree_add_item(btle_tree, hf_big_control_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- control_opcode = tvb_get_guint8(tvb, offset);
+ case 0x01: /* BIG_TERMINATE_IND */
+ proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset += 1;
+ proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
+ offset += 2;
+ break;
+
+ default:
+ offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
+ break;
+ }
+ break;
- col_add_fstr(pinfo->cinfo, COL_INFO, "BIG Control Opcode: %s",
- val_to_str_ext_const(control_opcode, &big_control_opcode_vals_ext, "Unknown"));
+ default:
+ if (tvb_reported_length_remaining(tvb, offset) > 3) {
+ proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
+ offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ }
+ }
- switch (control_opcode) {
- case 0x00: /* BIG_CHANNEL_MAP_IND */
- sub_item = proto_tree_add_item(btle_tree, hf_control_channel_map, tvb, offset, 5, ENC_NA);
- sub_tree = proto_item_add_subtree(sub_item, ett_channel_map);
+ return offset;
+}
- call_dissector(btcommon_le_channel_map_handle, tvb_new_subset_length(tvb, offset, 5), pinfo, sub_tree);
- offset += 5;
+static int
+dissect_btle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ proto_item *btle_item;
+ proto_tree *btle_tree;
+ proto_item *sub_item;
+ int offset = 0;
+ uint32_t access_address, length;
+ tvbuff_t *next_tvb;
+ connection_info_t *connection_info = NULL;
- proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- offset += 2;
- break;
+ uint8_t btle_pdu_type = BTLE_PDU_TYPE_UNKNOWN;
- case 0x01: /* BIG_TERMINATE_IND */
- proto_tree_add_item(btle_tree, hf_control_error_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset += 1;
- proto_tree_add_item_ret_uint(btle_tree, hf_control_instant, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_value);
- offset += 2;
- break;
+ uint32_t interface_id;
+ uint32_t adapter_id;
+ const btle_context_t *btle_context = get_btle_context(pinfo,
+ data,
+ &adapter_id,
+ &interface_id);
- default:
- offset = dissect_ctrl_pdu_without_data(tvb, pinfo, btle_tree, offset);
- break;
- }
- break;
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LE LL");
+
+ btle_item = proto_tree_add_item(tree, proto_btle, tvb, offset, -1, ENC_NA);
+ btle_tree = proto_item_add_subtree(btle_item, ett_btle);
+ sub_item = proto_tree_add_item(btle_tree, hf_access_address, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ access_address = tvb_get_letohl(tvb, offset);
+ if (btle_context) {
+ switch(btle_context->aa_category) {
+ case E_AA_MATCHED:
+ expert_add_info(pinfo, sub_item, &ei_access_address_matched);
+ break;
+ case E_AA_ILLEGAL:
+ expert_add_info(pinfo, sub_item, &ei_access_address_illegal);
+ break;
+ case E_AA_BIT_ERRORS:
+ expert_add_info(pinfo, sub_item, &ei_access_address_bit_errors);
+ break;
default:
- if (tvb_reported_length_remaining(tvb, offset) > 3) {
- proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
- }
+ break;
}
+ }
+ offset += 4;
+
+ if (btle_context && btle_context->phy == LE_CODED_PHY) {
+ proto_tree_add_item(btle_tree, hf_coding_indicator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+
+ if (btle_context) {
+ btle_pdu_type = btle_context->pdu_type;
+ }
+
+ if (btle_pdu_type == BTLE_PDU_TYPE_UNKNOWN) {
+ /* No context to provide us with physical channel pdu type, make an assumption from the access address */
+ btle_pdu_type = guess_btle_pdu_type_from_access(interface_id,
+ adapter_id,
+ access_address);
+ }
+ if (btle_pdu_type == BTLE_PDU_TYPE_ADVERTISING) {
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ length = dissect_btle_adv(next_tvb,
+ pinfo,
+ btle_tree,
+ btle_context,
+ adapter_id,
+ interface_id,
+ access_address) - 2;
+ offset += length + 2;
+ } else if (btle_pdu_type == BTLE_PDU_TYPE_DATA || btle_pdu_type == BTLE_PDU_TYPE_CONNECTEDISO) {
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ length = dissect_btle_acl_or_iso(next_tvb,
+ pinfo,
+ tree,
+ btle_tree,
+ btle_context,
+ adapter_id,
+ interface_id,
+ access_address,
+ btle_pdu_type) - 2;
+ offset += length + 2;
+ } else if (btle_pdu_type == BTLE_PDU_TYPE_BROADCASTISO) {
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ length = dissect_btle_broadcast_iso(next_tvb,
+ pinfo,
+ btle_tree,
+ adapter_id,
+ interface_id,
+ access_address) - 2;
+ offset += length + 2;
} else {
- /* Unknown physical channel PDU type */
+ /* Unknown physical channel PDU type. Assume CRC size is 3 bytes */
if (tvb_reported_length_remaining(tvb, offset) > 3) {
proto_tree_add_expert(btle_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_reported_length_remaining(tvb, offset) - 3);
- offset += tvb_reported_length_remaining(tvb, offset) - 3;
+ length = tvb_reported_length_remaining(tvb, offset) - 3;
+ offset += length;
+ } else {
+ /* Length is unknown. */
+ length = 0;
}
}
- /* BT spec Vol 6, Part B, Section 1.2: CRC is big endian and bits in byte are flipped */
- packet_crc = reverse_bits_per_byte(tvb_get_ntoh24(tvb, offset));
- sub_item = proto_tree_add_uint(btle_tree, hf_crc, tvb, offset, 3, packet_crc);
- offset += 3;
- if (crc_status == CRC_CAN_BE_CALCULATED) {
- guint32 crc = btle_crc(tvb, length, crc_init);
- crc_status = (packet_crc == crc) ? CRC_CORRECT : CRC_INCORRECT;
- }
- switch(crc_status) {
- case CRC_INDETERMINATE:
- expert_add_info(pinfo, sub_item, &ei_crc_cannot_be_determined);
- break;
- case CRC_INCORRECT:
- expert_add_info(pinfo, sub_item, &ei_crc_incorrect);
- break;
- case CRC_CORRECT:
- default:
- break;
- }
+ offset += dissect_crc(tvb,
+ btle_tree,
+ offset,
+ pinfo,
+ length,
+ connection_info,
+ btle_context,
+ access_address);
return offset;
}
@@ -4430,13 +4619,13 @@ proto_register_btle(void)
FT_UINT8, BASE_DEC, VALS(le_coding_indicators), 0x3,
NULL, HFILL }
},
- { &hf_master_bd_addr,
- { "Master Address", "btle.master_bd_addr",
+ { &hf_central_bd_addr,
+ { "Central Address", "btle.central_bd_addr",
FT_ETHER, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
- { &hf_slave_bd_addr,
- { "Slave Address", "btle.slave_bd_addr",
+ { &hf_peripheral_bd_addr,
+ { "Peripheral Address", "btle.peripheral_bd_addr",
FT_ETHER, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
@@ -4516,7 +4705,7 @@ proto_register_btle(void)
NULL, HFILL }
},
{ &hf_scan_response_data,
- { "Scan Response Data", "btle.scan_responce_data",
+ { "Scan Response Data", "btle.scan_response_data",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }
},
@@ -4726,7 +4915,7 @@ proto_register_btle(void)
NULL, HFILL }
},
{ &hf_extended_advertising_sync_info_reserved,
- { "Reserved", "btle.extended_advertising_header.sync_info.offset_units",
+ { "Reserved", "btle.extended_advertising_header.sync_info.reserved",
FT_BOOLEAN, 16, NULL, 0x8000,
NULL, HFILL }
},
@@ -4762,7 +4951,7 @@ proto_register_btle(void)
},
{ &hf_extended_advertising_tx_power,
{ "TX Power", "btle.extended_advertising_header.tx_power",
- FT_INT8, BASE_DEC | BASE_UNIT_STRING, &units_dbm, 0x0,
+ FT_INT8, BASE_DEC | BASE_UNIT_STRING, UNS(&units_dbm), 0x0,
NULL, HFILL }
},
{ &hf_extended_advertising_header_acad,
@@ -4925,8 +5114,8 @@ proto_register_btle(void)
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
- { &hf_control_feature_set_slave_initiated_features_exchange,
- { "Slave Initiated Features Exchange", "btle.control.feature_set.slave_initiated_features_exchange",
+ { &hf_control_feature_set_peripheral_initiated_features_exchange,
+ { "Peripheral Initiated Features Exchange", "btle.control.feature_set.peripheral_initiated_features_exchange",
FT_BOOLEAN, 8, NULL, 0x08,
NULL, HFILL }
},
@@ -5240,23 +5429,23 @@ proto_register_btle(void)
FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_master_session_key_diversifier,
- { "Master Session Key Diversifier", "btle.control.master_session_key_diversifier",
+ { &hf_control_central_session_key_diversifier,
+ { "Central Session Key Diversifier", "btle.control.central_session_key_diversifier",
FT_UINT64, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_slave_session_key_diversifier,
- { "Slave Session Key Diversifier", "btle.control.slave_session_key_diversifier",
+ { &hf_control_peripheral_session_key_diversifier,
+ { "Peripheral Session Key Diversifier", "btle.control.peripheral_session_key_diversifier",
FT_UINT64, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_master_session_initialization_vector,
- { "Master Session Initialization Vector", "btle.control.master_session_initialization_vector",
+ { &hf_control_central_session_initialization_vector,
+ { "Central Session Initialization Vector", "btle.control.central_session_initialization_vector",
FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_slave_session_initialization_vector,
- { "Slave Session Initialization Vector", "btle.control.slave_session_initialization_vector",
+ { &hf_control_peripheral_session_initialization_vector,
+ { "Peripheral Session Initialization Vector", "btle.control.peripheral_session_initialization_vector",
FT_UINT64, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL }
},
@@ -5267,7 +5456,7 @@ proto_register_btle(void)
},
{ &hf_control_max_rx_time,
{ "Max RX time", "btle.control.max_rx_time",
- FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0,
+ FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microsecond_microseconds), 0x0,
NULL, HFILL }
},
{ &hf_control_max_tx_octets,
@@ -5277,7 +5466,7 @@ proto_register_btle(void)
},
{ &hf_control_max_tx_time,
{ "Max TX time", "btle.control.max_tx_time",
- FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0,
+ FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microsecond_microseconds), 0x0,
NULL, HFILL }
},
{ &hf_control_phys_sender_le_1m_phy,
@@ -5325,52 +5514,52 @@ proto_register_btle(void)
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_m_to_s_phy,
- { "Master to Slave PHY", "btle.control.m_to_s_phy",
+ { &hf_control_c_to_p_phy,
+ { "Central to Peripheral PHY", "btle.control.m_to_s_phy",
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_m_to_s_phy_le_1m_phy,
+ { &hf_control_c_to_p_phy_le_1m_phy,
{ "LE 1M PHY", "btle.control.m_to_s_phy.le_1m_phy",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
- { &hf_control_m_to_s_phy_le_2m_phy,
+ { &hf_control_c_to_p_phy_le_2m_phy,
{ "LE 2M PHY", "btle.control.m_to_s_phy.le_2m_phy",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
- { &hf_control_m_to_s_phy_le_coded_phy,
+ { &hf_control_c_to_p_phy_le_coded_phy,
{ "LE Coded PHY", "btle.control.m_to_s_phy.le_coded_phy",
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
- { &hf_control_m_to_s_phy_reserved_bits,
+ { &hf_control_c_to_p_phy_reserved_bits,
{ "Reserved for future use", "btle.control.m_to_s_phy.reserved",
FT_UINT8, BASE_DEC, NULL, 0xF8,
NULL, HFILL }
},
- { &hf_control_s_to_m_phy,
- { "Slave to Master PHY", "btle.control.s_to_m_phy",
+ { &hf_control_p_to_c_phy,
+ { "Peripheral to Central PHY", "btle.control.s_to_m_phy",
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_s_to_m_phy_le_1m_phy,
+ { &hf_control_p_to_c_phy_le_1m_phy,
{ "LE 1M PHY", "btle.control.s_to_m_phy.le_1m_phy",
FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL }
},
- { &hf_control_s_to_m_phy_le_2m_phy,
+ { &hf_control_p_to_c_phy_le_2m_phy,
{ "LE 2M PHY", "btle.control.s_to_m_phy.le_2m_phy",
FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL }
},
- { &hf_control_s_to_m_phy_le_coded_phy,
+ { &hf_control_p_to_c_phy_le_coded_phy,
{ "LE Coded PHY", "btle.control.s_to_m_phy.le_coded_phy",
FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL }
},
- { &hf_control_s_to_m_phy_reserved_bits,
+ { &hf_control_p_to_c_phy_reserved_bits,
{ "Reserved for future use", "btle.control.s_to_m_phy.reserved",
FT_UINT8, BASE_DEC, NULL, 0xF8,
NULL, HFILL }
@@ -5436,7 +5625,7 @@ proto_register_btle(void)
NULL, HFILL }
},
{ &hf_control_sync_info_reserved,
- { "Reserved", "btle.control.sync_info.offset_units",
+ { "Reserved", "btle.control.sync_info.reserved",
FT_BOOLEAN, 16, NULL, 0x8000,
NULL, HFILL }
},
@@ -5515,8 +5704,8 @@ proto_register_btle(void)
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_max_sdu_m_to_s,
- { "Max_SDU_M_To_S", "btle.control.max_sdu_m_to_s",
+ { &hf_control_max_sdu_c_to_p,
+ { "Max_SDU_C_To_P", "btle.control.max_sdu_c_to_p",
FT_UINT16, BASE_DEC, NULL, 0x0fff,
NULL, HFILL }
},
@@ -5530,8 +5719,8 @@ proto_register_btle(void)
FT_BOOLEAN, 16, NULL, 0x8000,
NULL, HFILL }
},
- { &hf_control_max_sdu_s_to_m,
- { "Max_SDU_S_To_M", "btle.control.max_sdu_s_to_m",
+ { &hf_control_max_sdu_p_to_c,
+ { "Max_SDU_P_To_C", "btle.control.max_sdu_p_to_c",
FT_UINT16, BASE_DEC, NULL, 0x0fff,
NULL, HFILL }
},
@@ -5540,9 +5729,9 @@ proto_register_btle(void)
FT_UINT16, BASE_DEC, NULL, 0xf000,
"Reserved for Future Use", HFILL }
},
- { &hf_control_sdu_interval_m_to_s,
- { "SDU_Interval_M_To_S", "btle.control.sdu_interval_m_to_s",
- FT_UINT24, BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0fffff,
+ { &hf_control_sdu_interval_c_to_p,
+ { "SDU_Interval_C_To_P", "btle.control.sdu_interval_c_to_p",
+ FT_UINT24, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microsecond_microseconds), 0x0fffff,
NULL, HFILL }
},
{ &hf_control_rfu_3,
@@ -5550,9 +5739,9 @@ proto_register_btle(void)
FT_UINT24, BASE_DEC, NULL, 0xf00000,
"Reserved for Future Use", HFILL }
},
- { &hf_control_sdu_interval_s_to_m,
- { "SDU_Interval_S_To_M", "btle.control.sdu_interval_s_to_m",
- FT_UINT24, BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0fffff,
+ { &hf_control_sdu_interval_p_to_c,
+ { "SDU_Interval_P_To_C", "btle.control.sdu_interval_p_to_c",
+ FT_UINT24, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microsecond_microseconds), 0x0fffff,
NULL, HFILL }
},
{ &hf_control_rfu_4,
@@ -5560,13 +5749,13 @@ proto_register_btle(void)
FT_UINT24, BASE_DEC, NULL, 0xf00000,
"Reserved for Future Use", HFILL }
},
- { &hf_control_max_pdu_m_to_s,
- { "Max_PDU_M_To_S", "btle.control.max_pdu_m_to_s",
+ { &hf_control_max_pdu_c_to_p,
+ { "Max_PDU_C_To_P", "btle.control.max_pdu_c_to_p",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_max_pdu_s_to_m,
- { "Max_PDU_S_To_M", "btle.control.max_pdu_s_to_m",
+ { &hf_control_max_pdu_p_to_c,
+ { "Max_PDU_P_To_C", "btle.control.max_pdu_p_to_c",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
@@ -5577,26 +5766,26 @@ proto_register_btle(void)
},
{ &hf_control_sub_interval,
{ "Sub_Interval", "btle.control.sub_interval",
- FT_UINT24, BASE_DEC|BASE_UNIT_STRING, &units_microsecond_microseconds, 0x0,
+ FT_UINT24, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microsecond_microseconds), 0x0,
NULL, HFILL }
},
- { &hf_control_bn_m_to_s,
- { "BN_M_To_S", "btle.control.bn_m_to_s",
+ { &hf_control_bn_c_to_p,
+ { "BN_C_To_P", "btle.control.bn_c_to_p",
FT_UINT8, BASE_DEC, NULL, 0x0f,
NULL, HFILL }
},
- { &hf_control_bn_s_to_m,
- { "BN_S_To_M", "btle.control.bn_s_to_m",
+ { &hf_control_bn_p_to_c,
+ { "BN_P_To_C", "btle.control.bn_p_to_c",
FT_UINT8, BASE_DEC, NULL, 0xf0,
NULL, HFILL }
},
- { &hf_control_ft_m_to_s,
- { "FT_M_To_S", "btle.control.ft_m_to_s",
+ { &hf_control_ft_c_to_p,
+ { "FT_C_To_P", "btle.control.ft_c_to_p",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
- { &hf_control_ft_s_to_m,
- { "FT_S_To_M", "btle.control.ft_s_to_m",
+ { &hf_control_ft_p_to_c,
+ { "FT_P_To_C", "btle.control.ft_p_to_c",
FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
@@ -5952,7 +6141,7 @@ proto_register_btle(void)
{ "btle.nack", PI_SEQUENCE, PI_NOTE, "Not acknowledged", EXPFILL }},
};
- static gint *ett[] = {
+ static int *ett[] = {
&ett_btle,
&ett_advertising_header,
&ett_link_layer_data,
@@ -5968,8 +6157,8 @@ proto_register_btle(void)
&ett_features,
&ett_tx_phys,
&ett_rx_phys,
- &ett_m_to_s_phy,
- &ett_s_to_m_phy,
+ &ett_c_to_p_phy,
+ &ett_p_to_c_phy,
&ett_phys,
&ett_pwr_phy,
&ett_cte,
@@ -5983,6 +6172,7 @@ proto_register_btle(void)
};
connection_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+ periodic_adv_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
broadcastiso_connection_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
connection_parameter_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
adi_to_first_frame_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());