2014-12-18 14:54:38 +00:00
/* packet-btbredr_rf.c
* Routines for Bluetooth Pseudoheader for BR / EDR Baseband
*
* Copyright 2014 , Michal Labedzki for Tieto Corporation
* Copyright 2014 , Dominic Spill < dominicgs @ gmail . com >
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
2018-02-12 11:23:27 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
2014-12-18 14:54:38 +00:00
*/
# include "config.h"
# include <epan/packet.h>
# include <epan/expert.h>
# include <wiretap/wtap.h>
# include "packet-bluetooth.h"
static int proto_btbredr_rf = - 1 ;
static int hf_rf_channel = - 1 ;
static int hf_uncertain_rf_channel = - 1 ;
static int hf_signal_power = - 1 ;
static int hf_invalid_signal_power = - 1 ;
static int hf_noise_power = - 1 ;
static int hf_invalid_noise_power = - 1 ;
static int hf_access_address_offenses = - 1 ;
static int hf_payload_transport_rate = - 1 ;
static int hf_payload_transport_rate_payload = - 1 ;
static int hf_payload_transport_rate_transport = - 1 ;
static int hf_payload_transport_rate_ignored = - 1 ;
static int hf_corrected_header_bits = - 1 ;
static int hf_corrected_payload_bits = - 1 ;
static int hf_lower_address_part = - 1 ;
static int hf_reference_lower_address_part = - 1 ;
static int hf_invalid_reference_lower_address_part = - 1 ;
static int hf_reference_upper_addres_part = - 1 ;
static int hf_invalid_reference_upper_addres_part = - 1 ;
static int hf_whitened_packet_header = - 1 ;
static int hf_packet_header = - 1 ;
static int hf_packet_header_reserved = - 1 ;
static int hf_packet_header_lt_addr = - 1 ;
static int hf_packet_header_type = - 1 ;
static int hf_packet_header_type_any = - 1 ;
static int hf_packet_header_type_sco_br = - 1 ;
static int hf_packet_header_type_esco_br = - 1 ;
static int hf_packet_header_type_esco_edr = - 1 ;
static int hf_packet_header_type_acl_br = - 1 ;
static int hf_packet_header_type_acl_edr = - 1 ;
static int hf_packet_header_type_csb_br = - 1 ;
static int hf_packet_header_type_csb_edr = - 1 ;
static int hf_packet_header_flow_control = - 1 ;
static int hf_packet_header_acknowledge_indication = - 1 ;
static int hf_packet_header_sequence_number = - 1 ;
static int hf_packet_header_header_error_check = - 1 ;
static int hf_flags = - 1 ;
static int hf_flags_reserved_15_14 = - 1 ;
static int hf_flags_mic_pass = - 1 ;
static int hf_flags_mic_checked = - 1 ;
static int hf_flags_crc_pass = - 1 ;
static int hf_flags_crc_checked = - 1 ;
static int hf_flags_hec_pass = - 1 ;
static int hf_flags_hec_checked = - 1 ;
static int hf_flags_reference_upper_addres_part_valid = - 1 ;
static int hf_flags_rf_channel_aliasing = - 1 ;
static int hf_flags_br_edr_data_present = - 1 ;
static int hf_flags_reference_lower_address_part_valid = - 1 ;
static int hf_flags_bredr_payload_decrypted = - 1 ;
static int hf_flags_noise_power_valid = - 1 ;
static int hf_flags_signal_power_valid = - 1 ;
static int hf_flags_packet_header_and_br_edr_payload_dewhitened = - 1 ;
static int hf_whitened_data = - 1 ;
static int hf_encrypted_data = - 1 ;
static int hf_data = - 1 ;
# define FLAGS_MIC_PASS 0x2000
# define FLAGS_MIC_CHECKED 0x1000
# define FLAGS_CRC_PASS 0x0800
# define FLAGS_CRC_CHECKED 0x0400
# define FLAGS_HEC_PASS 0x0200
# define FLAGS_HEC_CHECKED 0x0100
# define FLAGS_REFERENCE_UPPER_ADDRES_PART_VALID 0x0080
# define FLAGS_RF_CHANNEL_ALIASING 0x0040
# define FLAGS_BR_EDR_DATA_PRESENT 0x0020
# define FLAGS_REFERENCE_LOWER_ADDRESS_PART_VALID 0x0010
# define FLAGS_BREDR_PAYLOAD_DECRYPTED 0x0008
# define FLAGS_NOISE_POWER_VALID 0x0004
# define FLAGS_SIGNAL_POWER_VALID 0x0002
# define FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED 0x0001
static const int * hfx_payload_transport_rate [ ] = {
& hf_payload_transport_rate_payload ,
& hf_payload_transport_rate_transport ,
NULL
} ;
static expert_field ei_unexpected_data = EI_INIT ;
static expert_field ei_reserved_not_zero = EI_INIT ;
static expert_field ei_incorrect_packet_header_or_hec = EI_INIT ;
static expert_field ei_packet_header_with_hec_not_checked = EI_INIT ;
static gint ett_btbredr_rf = - 1 ;
static gint ett_flags = - 1 ;
static gint ett_payload_transport_rate = - 1 ;
static gint ett_packet_header = - 1 ;
static gint ett_bluetooth_header = - 1 ;
static dissector_table_t packet_type_sco_br_table ;
static dissector_table_t packet_type_esco_br_table ;
static dissector_table_t packet_type_esco_edr_table ;
static dissector_table_t packet_type_acl_br_table ;
static dissector_table_t packet_type_acl_edr_table ;
static dissector_table_t packet_type_csb_br_table ;
static dissector_table_t packet_type_csb_edr_table ;
static dissector_handle_t btbredr_rf_handle ;
static const value_string payload_transport_rate_transport_vals [ ] = {
{ 0x00 , " Any " } ,
{ 0x01 , " SCO " } ,
{ 0x02 , " eSCO " } ,
{ 0x03 , " ACL " } ,
{ 0x04 , " CSB " } ,
{ 0 , NULL }
} ;
# define TRANSPORT_ANY 0x00
# define TRANSPORT_SCO 0x10
# define TRANSPORT_eSCO 0x20
# define TRANSPORT_ACL 0x30
# define TRANSPORT_CSB 0x40
static const value_string payload_transport_rate_payload_vals [ ] = {
{ 0x00 , " Basic Rate with GFSK demodulation " } ,
{ 0x01 , " Enhanced Data Rate with PI/2-DQPSK demodulation " } ,
{ 0x02 , " Enhanced Data Rate with 8DPSK demodulation " } ,
{ 0 , NULL }
} ;
static const value_string payload_transport_rate_payload_abbrev_vals [ ] = {
{ 0x00 , " BR 1Mbps " } ,
{ 0x01 , " EDR 2Mbps " } ,
{ 0x02 , " EDR 3Mbps " } ,
{ 0 , NULL }
} ;
# define PAYLOAD_BR 0x00
# define PAYLOAD_EDR_2 0x01
# define PAYLOAD_EDR_3 0x02
# define PACKET_TYPE_UNKNOWN -1
static const value_string packet_type_any_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " FHS " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " DH1/2-DH1 " } ,
{ 0x05 , " HV1 " } ,
{ 0x06 , " HV2/2-EV3 " } ,
{ 0x07 , " HV3/EV3/3-EV3 " } ,
{ 0x08 , " DV/3-DH1 " } ,
{ 0x09 , " AUX1 " } ,
{ 0x0A , " DM3/2-DH3 " } ,
{ 0x0B , " DH3/3-DH3 " } ,
{ 0x0C , " EV4/2-EV5 " } ,
{ 0x0D , " EV5/3-EV5 " } ,
{ 0x0E , " DM5/2-DH5 " } ,
{ 0x0F , " DH5/3-DH5 " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_sco_br_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " FHS " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " undefined " } ,
{ 0x05 , " HV1 " } ,
{ 0x06 , " HV2 " } ,
{ 0x07 , " HV3 " } ,
{ 0x08 , " DV " } ,
{ 0x09 , " undefined " } ,
{ 0x0A , " undefined " } ,
{ 0x0B , " undefined " } ,
{ 0x0C , " undefined " } ,
{ 0x0D , " undefined " } ,
{ 0x0E , " undefined " } ,
{ 0x0F , " undefined " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_esco_br_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " reserved " } ,
{ 0x03 , " reserved " } ,
{ 0x04 , " undefined " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " undefined " } ,
{ 0x07 , " EV3 " } ,
{ 0x08 , " undefined " } ,
{ 0x09 , " undefined " } ,
{ 0x0A , " undefined " } ,
{ 0x0B , " undefined " } ,
{ 0x0C , " EV4 " } ,
{ 0x0D , " EV5 " } ,
{ 0x0E , " undefined " } ,
{ 0x0F , " undefined " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_esco_edr_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " reserved " } ,
{ 0x03 , " reserved " } ,
{ 0x04 , " undefined " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " 2-EV3 " } ,
{ 0x07 , " 3-EV3 " } ,
{ 0x08 , " undefined " } ,
{ 0x09 , " undefined " } ,
{ 0x0A , " undefined " } ,
{ 0x0B , " undefined " } ,
{ 0x0C , " 2-EV5 " } ,
{ 0x0D , " 3-EV5 " } ,
{ 0x0E , " undefined " } ,
{ 0x0F , " undefined " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_acl_br_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " FHS " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " DH1 " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " undefined " } ,
{ 0x07 , " undefined " } ,
{ 0x08 , " undefined " } ,
{ 0x09 , " AUX1 " } ,
{ 0x0A , " DM3 " } ,
{ 0x0B , " DH3 " } ,
{ 0x0C , " undefined " } ,
{ 0x0D , " undefined " } ,
{ 0x0E , " DM5 " } ,
{ 0x0F , " DH5 " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_acl_edr_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " POLL " } ,
{ 0x02 , " FHS " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " 2-DH1 " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " undefined " } ,
{ 0x07 , " undefined " } ,
{ 0x08 , " 3-DH1 " } ,
{ 0x09 , " AUX1 " } ,
{ 0x0A , " 2-DH3 " } ,
{ 0x0B , " 3-DH3 " } ,
{ 0x0C , " undefined " } ,
{ 0x0D , " undefined " } ,
{ 0x0E , " 2-DH5 " } ,
{ 0x0F , " 3-DH5 " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_csb_br_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " reserved " } ,
{ 0x02 , " reserved " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " DH1 " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " undefined " } ,
{ 0x07 , " undefined " } ,
{ 0x08 , " undefined " } ,
{ 0x09 , " undefined " } ,
{ 0x0A , " DM3 " } ,
{ 0x0B , " DH3 " } ,
{ 0x0C , " undefined " } ,
{ 0x0D , " undefined " } ,
{ 0x0E , " DM5 " } ,
{ 0x0F , " DH5 " } ,
{ 0 , NULL }
} ;
static const value_string packet_type_csb_edr_vals [ ] = {
{ 0x00 , " NULL " } ,
{ 0x01 , " reserved " } ,
{ 0x02 , " reserved " } ,
{ 0x03 , " DM1 " } ,
{ 0x04 , " 2-DH1 " } ,
{ 0x05 , " undefined " } ,
{ 0x06 , " undefined " } ,
{ 0x07 , " undefined " } ,
{ 0x08 , " 3-DH1 " } ,
{ 0x09 , " undefined " } ,
{ 0x0A , " 2-DH3 " } ,
{ 0x0B , " 3-DH3 " } ,
{ 0x0C , " undefined " } ,
{ 0x0D , " undefined " } ,
{ 0x0E , " 2-DH5 " } ,
{ 0x0F , " 3-DH5 " } ,
{ 0 , NULL }
} ;
void proto_register_btbredr_rf ( void ) ;
void proto_reg_handoff_btbredr_rf ( void ) ;
static guint8 reverse_bits ( guint8 value )
{
return ( value & 0x80 ) > > 7 | ( value & 0x40 ) > > 5 | ( value & 0x20 ) > > 3 |
( value & 0x10 ) > > 1 | ( value & 0x08 ) < < 1 | ( value & 0x04 ) < < 3 |
( value & 0x02 ) < < 5 | ( value & 0x01 ) < < 7 ;
}
static gboolean check_hec ( guint8 uap , guint32 header )
{
guint8 hec ;
guint16 header_data ;
guint8 lfsr ;
gint8 i ;
hec = header & 0xFF ;
header_data = ( header > > 8 ) & 0x3F ;
lfsr = uap ;
for ( i = 9 ; i > = 0 ; i - = 1 ) {
if ( lfsr & 0x80 )
lfsr ^ = 0x65 ;
lfsr = ( lfsr < < 1 ) | ( ( ( lfsr > > 7 ) ^ ( header_data > > i ) ) & 0x01 ) ;
}
lfsr = reverse_bits ( lfsr ) ;
return lfsr = = hec ;
}
static gint
dissect_btbredr_rf ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
{
proto_item * btbredr_rf_item ;
proto_tree * btbredr_rf_tree ;
proto_item * flags_item ;
proto_tree * flags_tree ;
proto_item * header_item ;
proto_tree * header_tree ;
proto_item * reserved_item ;
proto_item * hec_item = NULL ;
gint offset = 0 ;
gint hf_x ;
guint16 flags ;
guint8 payload_and_transport ;
gint16 packet_type = PACKET_TYPE_UNKNOWN ;
const gchar * packet_type_str = " Unknown " ;
dissector_table_t packet_type_table = NULL ;
bluetooth_data_t * bluetooth_data = ( bluetooth_data_t * ) data ;
btbredr_rf_item = proto_tree_add_item ( tree , proto_btbredr_rf , tvb , offset , - 1 , ENC_NA ) ;
btbredr_rf_tree = proto_item_add_subtree ( btbredr_rf_item , ett_btbredr_rf ) ;
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " BT BR/EDR RF " ) ;
if ( tvb_captured_length ( tvb ) > = 21 ) {
flags = tvb_get_guint16 ( tvb , 20 , ENC_LITTLE_ENDIAN ) ;
} else {
flags = 0 ;
}
if ( flags & FLAGS_RF_CHANNEL_ALIASING )
hf_x = hf_uncertain_rf_channel ;
else
hf_x = hf_rf_channel ;
proto_tree_add_item ( btbredr_rf_tree , hf_x , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
if ( flags & FLAGS_SIGNAL_POWER_VALID )
hf_x = hf_signal_power ;
else
hf_x = hf_invalid_signal_power ;
proto_tree_add_item ( btbredr_rf_tree , hf_x , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
if ( flags & FLAGS_NOISE_POWER_VALID )
hf_x = hf_noise_power ;
else
hf_x = hf_invalid_noise_power ;
proto_tree_add_item ( btbredr_rf_tree , hf_x , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
proto_tree_add_item ( btbredr_rf_tree , hf_access_address_offenses , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
payload_and_transport = tvb_get_guint8 ( tvb , offset ) ;
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Transport: %s (%s), RF Channel: %s%2u " ,
val_to_str_const ( payload_and_transport > > 4 , payload_transport_rate_transport_vals , " Unknown " ) ,
val_to_str_const ( payload_and_transport & 0xF , payload_transport_rate_payload_abbrev_vals , " Unknown " ) ,
( flags & FLAGS_RF_CHANNEL_ALIASING ) ? " ~ " : " " ,
tvb_get_guint8 ( tvb , 0 ) ) ;
if ( payload_and_transport = = 0xFF )
proto_tree_add_item ( btbredr_rf_tree , hf_payload_transport_rate_ignored , tvb , offset , 1 , ENC_NA ) ;
else
proto_tree_add_bitmask ( btbredr_rf_tree , tvb , offset , hf_payload_transport_rate , ett_payload_transport_rate , hfx_payload_transport_rate , ENC_LITTLE_ENDIAN ) ;
offset + = 1 ;
proto_tree_add_item ( btbredr_rf_tree , hf_corrected_header_bits , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
proto_tree_add_item ( btbredr_rf_tree , hf_corrected_payload_bits , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
offset + = 2 ;
proto_tree_add_item ( btbredr_rf_tree , hf_lower_address_part , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
offset + = 4 ;
if ( flags & FLAGS_REFERENCE_LOWER_ADDRESS_PART_VALID )
hf_x = hf_reference_lower_address_part ;
else
hf_x = hf_invalid_reference_lower_address_part ;
proto_tree_add_item ( btbredr_rf_tree , hf_x , tvb , offset , 3 , ENC_LITTLE_ENDIAN ) ;
offset + = 3 ;
if ( flags & FLAGS_REFERENCE_UPPER_ADDRES_PART_VALID )
hf_x = hf_reference_upper_addres_part ;
else
hf_x = hf_invalid_reference_upper_addres_part ;
proto_tree_add_item ( btbredr_rf_tree , hf_x , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
if ( ! ( flags & FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED ) ) {
2016-04-13 17:41:30 +00:00
proto_tree_add_item ( btbredr_rf_tree , hf_whitened_packet_header , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2014-12-18 14:54:38 +00:00
} else {
header_item = proto_tree_add_item ( btbredr_rf_tree , hf_packet_header , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
header_tree = proto_item_add_subtree ( header_item , ett_bluetooth_header ) ;
proto_tree_add_item ( header_tree , hf_packet_header_reserved , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_packet_header_lt_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
if ( payload_and_transport = = ( TRANSPORT_SCO | PAYLOAD_BR ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_sco_br , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_sco_br_vals , " Unknown " ) ;
packet_type_table = packet_type_sco_br_table ;
} else if ( payload_and_transport = = ( TRANSPORT_eSCO | PAYLOAD_BR ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_esco_br , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_esco_br_vals , " Unknown " ) ;
packet_type_table = packet_type_esco_br_table ;
} else if ( payload_and_transport = = ( TRANSPORT_eSCO | PAYLOAD_EDR_2 ) | | payload_and_transport = = ( TRANSPORT_eSCO | PAYLOAD_EDR_3 ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_esco_edr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_esco_edr_vals , " Unknown " ) ;
packet_type_table = packet_type_esco_edr_table ;
} else if ( payload_and_transport = = ( TRANSPORT_ACL | PAYLOAD_BR ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_acl_br , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_acl_br_vals , " Unknown " ) ;
packet_type_table = packet_type_acl_br_table ;
} else if ( payload_and_transport = = ( TRANSPORT_ACL | PAYLOAD_EDR_2 ) | | payload_and_transport = = ( TRANSPORT_ACL | PAYLOAD_EDR_3 ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_acl_edr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_acl_edr_vals , " Unknown " ) ;
packet_type_table = packet_type_acl_edr_table ;
} else if ( payload_and_transport = = ( TRANSPORT_CSB | PAYLOAD_BR ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_csb_br , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_csb_br_vals , " Unknown " ) ;
packet_type_table = packet_type_csb_br_table ;
} else if ( payload_and_transport = = ( TRANSPORT_CSB | PAYLOAD_EDR_2 ) | | payload_and_transport = = ( TRANSPORT_ACL | PAYLOAD_EDR_3 ) ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_csb_edr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_csb_edr_vals , " Unknown " ) ;
packet_type_table = packet_type_csb_edr_table ;
} else if ( ( payload_and_transport > > 4 ) = = TRANSPORT_ANY ) {
proto_tree_add_item ( header_tree , hf_packet_header_type_any , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
packet_type = ( tvb_get_guint8 ( tvb , offset + 1 ) > > 3 ) & 0xF ;
packet_type_str = val_to_str_const ( packet_type , packet_type_any_vals , " Unknown " ) ;
} else {
proto_tree_add_item ( header_tree , hf_packet_header_type , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
}
proto_tree_add_item ( header_tree , hf_packet_header_flow_control , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_packet_header_acknowledge_indication , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_packet_header_sequence_number , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
hec_item = proto_tree_add_item ( header_tree , hf_packet_header_header_error_check , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
}
if ( ( flags & FLAGS_REFERENCE_UPPER_ADDRES_PART_VALID ) & &
( flags & FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED ) & &
! check_hec ( tvb_get_guint8 ( tvb , offset - 1 ) , tvb_get_guint32 ( tvb , offset , ENC_LITTLE_ENDIAN ) ) ) {
expert_add_info ( pinfo , hec_item , & ei_incorrect_packet_header_or_hec ) ;
}
if ( ! ( ( flags & FLAGS_REFERENCE_UPPER_ADDRES_PART_VALID ) & &
( flags & FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED ) ) ) {
expert_add_info ( pinfo , hec_item , & ei_packet_header_with_hec_not_checked ) ;
}
offset + = 4 ;
flags_item = proto_tree_add_item ( btbredr_rf_tree , hf_flags , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
flags_tree = proto_item_add_subtree ( flags_item , ett_flags ) ;
flags = tvb_get_guint16 ( tvb , offset , ENC_LITTLE_ENDIAN ) ;
reserved_item = proto_tree_add_item ( flags_tree , hf_flags_reserved_15_14 , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
if ( flags & 0xC000 ) {
expert_add_info ( pinfo , reserved_item , & ei_reserved_not_zero ) ;
}
proto_tree_add_item ( flags_tree , hf_flags_mic_pass , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_mic_checked , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_crc_pass , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_crc_checked , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_hec_pass , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_hec_checked , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_reference_upper_addres_part_valid , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_rf_channel_aliasing , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_br_edr_data_present , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_reference_lower_address_part_valid , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_bredr_payload_decrypted , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_noise_power_valid , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_signal_power_valid , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_flags_packet_header_and_br_edr_payload_dewhitened , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
offset + = 2 ;
if ( ( flags & ( FLAGS_SIGNAL_POWER_VALID | FLAGS_NOISE_POWER_VALID ) ) = = ( FLAGS_SIGNAL_POWER_VALID | FLAGS_NOISE_POWER_VALID ) ) {
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (SP: %4i, NP: %4i) " ,
2018-04-10 06:06:47 +00:00
( gint ) tvb_get_gint8 ( tvb , 1 ) , ( gint ) tvb_get_gint8 ( tvb , 2 ) ) ;
2014-12-18 14:54:38 +00:00
} else if ( flags & FLAGS_SIGNAL_POWER_VALID ) {
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (SP: %4i) " ,
2018-04-10 06:06:47 +00:00
( gint ) tvb_get_gint8 ( tvb , 1 ) ) ;
2014-12-18 14:54:38 +00:00
} else if ( flags & FLAGS_NOISE_POWER_VALID ) {
col_append_fstr ( pinfo - > cinfo , COL_INFO , " (NP: %4i) " ,
2018-04-10 06:06:47 +00:00
( gint ) tvb_get_gint8 ( tvb , 2 ) ) ;
2014-12-18 14:54:38 +00:00
}
if ( flags & FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED )
col_append_fstr ( pinfo - > cinfo , COL_INFO , " , Packet Type: %s " , packet_type_str ) ;
if ( flags & FLAGS_BR_EDR_DATA_PRESENT ) {
if ( flags & FLAGS_PACKET_HEADER_AND_BR_EDR_PAYLOAD_DEWHITENED ) {
if ( flags & FLAGS_BREDR_PAYLOAD_DECRYPTED ) {
tvbuff_t * next_tvb ;
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
if ( ! ( packet_type_table & & packet_type > PACKET_TYPE_UNKNOWN & &
dissector_try_uint_new ( packet_type_table , packet_type , next_tvb , pinfo , tree , TRUE , bluetooth_data ) ) )
proto_tree_add_item ( btbredr_rf_tree , hf_data , tvb , offset , tvb_captured_length_remaining ( tvb , offset ) , ENC_NA ) ;
offset = tvb_reported_length ( tvb ) ;
} else {
proto_tree_add_item ( btbredr_rf_tree , hf_encrypted_data , tvb , offset , tvb_captured_length_remaining ( tvb , offset ) , ENC_NA ) ;
offset = tvb_reported_length ( tvb ) ;
}
} else {
2016-04-13 05:59:01 +00:00
proto_tree_add_item ( btbredr_rf_tree , hf_whitened_data , tvb , offset , tvb_captured_length_remaining ( tvb , offset ) , ENC_NA ) ;
offset = tvb_reported_length ( tvb ) ;
2014-12-18 14:54:38 +00:00
}
} else {
if ( tvb_captured_length_remaining ( tvb , offset ) > 0 )
2016-04-13 05:59:01 +00:00
proto_tree_add_expert ( btbredr_rf_tree , pinfo , & ei_unexpected_data , tvb , offset , tvb_captured_length_remaining ( tvb , offset ) ) ;
offset = tvb_reported_length ( tvb ) ;
2014-12-18 14:54:38 +00:00
}
return offset ;
}
void
proto_register_btbredr_rf ( void )
{
expert_module_t * expert_module ;
static hf_register_info hf [ ] = {
{ & hf_rf_channel ,
{ " RF Channel " , " btbredr_rf.rf_channel " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_uncertain_rf_channel ,
{ " Uncertain RF Channel " , " btbredr_rf.uncertain_rf_channel " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_signal_power ,
{ " Signal Power " , " btbredr_rf.signal_power " ,
FT_INT8 , BASE_DEC , NULL , 0x00 ,
" Signal Power in dBm " , HFILL }
} ,
{ & hf_invalid_signal_power ,
{ " Invalid Signal Power " , " btbredr_rf.invalid.signal_power " ,
FT_INT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_noise_power ,
{ " Noise Power " , " btbredr_rf.noise_power " ,
FT_INT8 , BASE_DEC , NULL , 0x00 ,
" Noise Power in dBm " , HFILL }
} ,
{ & hf_invalid_noise_power ,
{ " Invalid Noise Power " , " btbredr_rf.invalid.noise_power " ,
FT_INT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_access_address_offenses ,
{ " Access Address Offenses " , " btbredr_rf.access_address_offenses " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_payload_transport_rate ,
{ " Payload Transport Rate " , " btbredr_rf.payload_transport_rate " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_payload_transport_rate_ignored ,
{ " Payload Transport Rate: Ignored " , " btbredr_rf.payload_transport_rate.ignored " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
" BT Packet Header is ignored and there is no payload " , HFILL }
} ,
{ & hf_payload_transport_rate_transport ,
{ " Transport " , " btbredr_rf.payload_transport_rate.transport " ,
FT_UINT8 , BASE_HEX , VALS ( payload_transport_rate_transport_vals ) , 0xF0 ,
NULL , HFILL }
} ,
{ & hf_payload_transport_rate_payload ,
{ " Payload " , " btbredr_rf.payload_transport_rate.payload " ,
FT_UINT8 , BASE_HEX , VALS ( payload_transport_rate_payload_vals ) , 0x0F ,
NULL , HFILL }
} ,
{ & hf_corrected_header_bits ,
{ " Corrected Header Bits " , " btbredr_rf.corrected_header_bits " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_corrected_payload_bits ,
{ " Corrected Payload Bits " , " btbredr_rf.corrected_payload_bits " ,
FT_INT16 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_lower_address_part ,
{ " Lower Address Part " , " btbredr_rf.lower_address_part " ,
FT_UINT32 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_reference_lower_address_part ,
{ " Reference Lower Address Part " , " btbredr_rf.reference_lower_address_part " ,
FT_UINT24 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_invalid_reference_lower_address_part ,
{ " Invalid Reference Lower Address Part " , " btbredr_rf.invalid.reference_lower_address_part " ,
FT_UINT24 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_reference_upper_addres_part ,
{ " Reference Upper Address Part " , " btbredr_rf.reference_upper_addres_part " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_invalid_reference_upper_addres_part ,
{ " Invalid Reference Upper Address Part " , " btbredr_rf.invalid.reference_upper_addres_part " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_whitened_packet_header ,
{ " Whitened Packet Header " , " btbredr_rf.whitened.packet_header " ,
FT_UINT32 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_packet_header ,
{ " Packet Header " , " btbredr_rf.packet_header " ,
FT_UINT32 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_packet_header_reserved ,
{ " Reserved " , " btbredr_rf.packet_header.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFC0000 ,
NULL , HFILL }
} ,
{ & hf_packet_header_lt_addr ,
{ " LT_ADDR " , " btbredr_rf.packet_header.lt_addr " ,
FT_UINT32 , BASE_HEX , NULL , 0x00038000 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , NULL , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_any ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_any_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_sco_br ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_sco_br_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_esco_br ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_esco_br_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_esco_edr ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_esco_edr_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_acl_br ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_acl_br_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_acl_edr ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_acl_edr_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_csb_br ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_csb_br_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_type_csb_edr ,
{ " Type " , " btbredr_rf.packet_header.type " ,
FT_UINT32 , BASE_HEX , VALS ( packet_type_csb_edr_vals ) , 0x00007800 ,
NULL , HFILL }
} ,
{ & hf_packet_header_flow_control ,
{ " Flow Control " , " btbredr_rf.packet_header.flow_control " ,
FT_BOOLEAN , 32 , NULL , 0x00000400 ,
NULL , HFILL }
} ,
{ & hf_packet_header_acknowledge_indication ,
{ " ARQN " , " btbredr_rf.packet_header.arqn " ,
FT_BOOLEAN , 32 , NULL , 0x00000200 ,
" Acknowledge Indication " , HFILL }
} ,
{ & hf_packet_header_sequence_number ,
{ " SEQN " , " btbredr_rf.packet_header.seqn " ,
FT_BOOLEAN , 32 , NULL , 0x00000100 ,
" Sequence Number " , HFILL }
} ,
{ & hf_packet_header_header_error_check ,
{ " HEC " , " btbredr_rf.packet_header.hec " ,
FT_UINT32 , BASE_HEX , NULL , 0x000000FF ,
" Header Error Check " , HFILL }
} ,
{ & hf_flags ,
{ " Flags " , " btbredr_rf.flags " ,
FT_UINT16 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_whitened_data ,
{ " Whitened Data " , " btbredr_rf.whitened.data " ,
FT_NONE , BASE_NONE , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_encrypted_data ,
{ " Encrypted Data " , " btbredr_rf.encrypted.data " ,
FT_NONE , BASE_NONE , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_data ,
{ " Data " , " btbredr_rf.data " ,
FT_NONE , BASE_NONE , NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_flags_reserved_15_14 ,
{ " Reserved " , " btbredr_rf.flags.reserved.15_14 " ,
FT_UINT16 , BASE_HEX , NULL , 0xC000 ,
NULL , HFILL }
} ,
{ & hf_flags_mic_pass ,
{ " MIC Pass " , " btbredr_rf.flags.mic_pass " ,
FT_BOOLEAN , 16 , NULL , 0x2000 ,
NULL , HFILL }
} ,
{ & hf_flags_mic_checked ,
{ " MIC Checked " , " btbredr_rf.flags.mic_check " ,
FT_BOOLEAN , 16 , NULL , 0x1000 ,
NULL , HFILL }
} ,
{ & hf_flags_crc_pass ,
{ " CRC Pass " , " btbredr_rf.flags.crc_pass " ,
FT_BOOLEAN , 16 , NULL , 0x0800 ,
NULL , HFILL }
} ,
{ & hf_flags_crc_checked ,
{ " CRC Checked " , " btbredr_rf.flags.crc_check " ,
FT_BOOLEAN , 16 , NULL , 0x0400 ,
NULL , HFILL }
} ,
{ & hf_flags_hec_pass ,
{ " HEC Pass " , " btbredr_rf.flags.hec_pass " ,
FT_BOOLEAN , 16 , NULL , 0x0200 ,
NULL , HFILL }
} ,
{ & hf_flags_hec_checked ,
{ " HEC Checked " , " btbredr_rf.flags.hec_check " ,
FT_BOOLEAN , 16 , NULL , 0x0100 ,
NULL , HFILL }
} ,
{ & hf_flags_reference_upper_addres_part_valid ,
{ " Reference Upper Address Part Valid " , " btbredr_rf.flags.reference_upper_addres_part_valid " ,
FT_BOOLEAN , 16 , NULL , 0x0080 ,
NULL , HFILL }
} ,
{ & hf_flags_rf_channel_aliasing ,
{ " RF Channel Aliasing " , " btbredr_rf.flags.rf_channel_aliasing " ,
FT_BOOLEAN , 16 , NULL , 0x0040 ,
NULL , HFILL }
} ,
{ & hf_flags_br_edr_data_present ,
{ " BR or EDR Data Present " , " btbredr_rf.flags.bredr_data_present " ,
FT_BOOLEAN , 16 , NULL , 0x0020 ,
NULL , HFILL }
} ,
{ & hf_flags_reference_lower_address_part_valid ,
{ " Reference Lower Address Part Valid " , " btbredr_rf.flags.reference_lower_address_part_valid " ,
FT_BOOLEAN , 16 , NULL , 0x0010 ,
NULL , HFILL }
} ,
{ & hf_flags_bredr_payload_decrypted ,
{ " BR or EDR Payload Decrypted " , " btbredr_rf.flags.bredr_payload_decrypted " ,
FT_BOOLEAN , 16 , NULL , 0x0008 ,
NULL , HFILL }
} ,
{ & hf_flags_noise_power_valid ,
{ " Noise Power Valid " , " btbredr_rf.flags.noise_power_valid " ,
FT_BOOLEAN , 16 , NULL , 0x0004 ,
NULL , HFILL }
} ,
{ & hf_flags_signal_power_valid ,
{ " Signal Power Valid " , " btbredr_rf.flags.signal_power_valid " ,
FT_BOOLEAN , 16 , NULL , 0x0002 ,
NULL , HFILL }
} ,
{ & hf_flags_packet_header_and_br_edr_payload_dewhitened ,
{ " Packet Header and BR/EDR Payload Dewhitened " , " btbredr_rf.flags.pkt_hdr_and_br_edr_payload_dewhitened " ,
FT_BOOLEAN , 16 , NULL , 0x0001 ,
NULL , HFILL }
}
} ;
static gint * ett [ ] = {
& ett_btbredr_rf ,
& ett_flags ,
& ett_payload_transport_rate ,
& ett_packet_header ,
& ett_bluetooth_header
} ;
static ei_register_info ei [ ] = {
{ & ei_unexpected_data , { " btbredr_rf.unexpected_data " , PI_PROTOCOL , PI_WARN , " Unexpected data, BR or EDR Data Present flag is set to False " , EXPFILL } } ,
{ & ei_reserved_not_zero , { " btbredr_rf.reserved_not_zero " , PI_PROTOCOL , PI_WARN , " Reserved values are not zeros " , EXPFILL } } ,
{ & ei_incorrect_packet_header_or_hec , { " btbredr_rf.incorrect_packet_header_or_hec " , PI_PROTOCOL , PI_WARN , " Incorrect Packet Header or HEC " , EXPFILL } } ,
{ & ei_packet_header_with_hec_not_checked , { " btbredr_rf.packet_header_with_hec_not_checked " , PI_PROTOCOL , PI_NOTE , " Packet Header with HEC is not checked " , EXPFILL } } ,
} ;
proto_btbredr_rf = proto_register_protocol ( " Bluetooth Pseudoheader for BR/EDR " , " BT BR/EDR RF " , " btbredr_rf " ) ;
proto_register_field_array ( proto_btbredr_rf , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
btbredr_rf_handle = register_dissector ( " btbredr_rf " , dissect_btbredr_rf , proto_btbredr_rf ) ;
2016-08-30 22:51:54 +00:00
packet_type_sco_br_table = register_dissector_table ( " btbredr_rf.packet_type.sco.br " , " BT Packet Type for SCO BR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_esco_br_table = register_dissector_table ( " btbredr_rf.packet_type.esco.br " , " BT Packet Type for eSCO BR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_esco_edr_table = register_dissector_table ( " btbredr_rf.packet_type.esco.edr " , " BT Packet Type for eSCO EDR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_acl_br_table = register_dissector_table ( " btbredr_rf.packet_type.acl.br " , " BT Packet Type for ACL BR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_acl_edr_table = register_dissector_table ( " btbredr_rf.packet_type.acl.edr " , " BT Packet Type for ACL EDR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_csb_br_table = register_dissector_table ( " btbredr_rf.packet_type.csb.br " , " BT Packet Type for CSB BR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
packet_type_csb_edr_table = register_dissector_table ( " btbredr_rf.packet_type.csb.edr " , " BT Packet Type for CSB EDR " , proto_btbredr_rf , FT_UINT8 , BASE_HEX ) ;
2014-12-18 14:54:38 +00:00
expert_module = expert_register_protocol ( proto_btbredr_rf ) ;
expert_register_field_array ( expert_module , ei , array_length ( ei ) ) ;
}
void
proto_reg_handoff_btbredr_rf ( void )
{
dissector_add_uint ( " bluetooth.encap " , WTAP_ENCAP_BLUETOOTH_BREDR_BB , btbredr_rf_handle ) ;
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/