aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
authorBill Meier <wmeier@newsguy.com>2012-03-12 14:38:59 +0000
committerBill Meier <wmeier@newsguy.com>2012-03-12 14:38:59 +0000
commitba2cda4ef0e5a13e3d1d22cc21fb0220d2de2056 (patch)
tree5db7c3abd3c87e02e341a049ea84a3f35219403d /epan/dissectors
parent3394b453aff33812913c78ae6eacdbfe6763ced1 (diff)
Cleanup & minor bug fixes:
- Don't put a value_string array in a .h file (included in several .c files); - 'if ((a!=NULL) && !b) {fail}' should be 'if ((a==NULL) || !b) {fail}' in a few cases; - Use value_string_ext as appropriate; - Use val_to_str_const() in place of val_to_str() as appropriate; - Use tvb_new_subset_remaining(...) instead of tvb_new_subset(..., -1, -1); - Use tvb_reported_length_remaining() in place of tvb_length_remaining() in some cases; - tvb_reported_length_remaining() can return -1; - Use of TFS(&true_false) not req'd since "True"/"False" is the default if no TFS provided; - Reformat various (long lines, etc); - Use consistent indentation. svn path=/trunk/; revision=41502
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/packet-btl2cap.c3005
-rw-r--r--epan/dissectors/packet-btl2cap.h32
-rw-r--r--epan/dissectors/packet-btobex.c1033
-rw-r--r--epan/dissectors/packet-btrfcomm.c1449
-rw-r--r--epan/dissectors/packet-btrfcomm.h6
-rw-r--r--epan/dissectors/packet-btsdp.c1662
-rw-r--r--epan/dissectors/packet-btsdp.h100
7 files changed, 3656 insertions, 3631 deletions
diff --git a/epan/dissectors/packet-btl2cap.c b/epan/dissectors/packet-btl2cap.c
index dba143cbf8..fc02d1dca8 100644
--- a/epan/dissectors/packet-btl2cap.c
+++ b/epan/dissectors/packet-btl2cap.c
@@ -140,449 +140,452 @@ static dissector_table_t l2cap_service_dissector_table;
/* This table maps cid values to psm values.
* The same table is used both for SCID and DCID.
- * For received CIDs we mask the cid with 0x8000 in this table
+ * For received CIDs we 'or' the cid with 0x8000 in this table
* Table is indexed by array: CID and frame number which created CID
*/
-static emem_tree_t *cid_to_psm_table = NULL;
+static emem_tree_t *cid_to_psm_table = NULL;
static emem_tree_t *psm_to_service_table = NULL;
typedef struct _config_data_t {
- guint8 mode;
- guint8 txwindow;
- emem_tree_t *start_fragments; /* indexed by pinfo->fd->num */
+ guint8 mode;
+ guint8 txwindow;
+ emem_tree_t *start_fragments; /* indexed by pinfo->fd->num */
} config_data_t;
+
typedef struct _psm_data_t {
- guint16 scid;
- guint16 dcid;
- guint16 psm;
- gboolean local_service;
- config_data_t in;
- config_data_t out;
+ guint16 scid;
+ guint16 dcid;
+ guint16 psm;
+ gboolean local_service;
+ config_data_t in;
+ config_data_t out;
} psm_data_t;
static const value_string command_code_vals[] = {
- { 0x01, "Command Reject" },
- { 0x02, "Connection Request" },
- { 0x03, "Connection Response" },
- { 0x04, "Configure Request" },
- { 0x05, "Configure Response" },
- { 0x06, "Disconnect Request" },
- { 0x07, "Disconnect Response" },
- { 0x08, "Echo Request" },
- { 0x09, "Echo Response" },
- { 0x0A, "Information Request" },
- { 0x0B, "Information Response" },
- { 0x0C, "Create Channel Request" },
- { 0x0D, "Create Channel Response" },
- { 0x0E, "Move Channel Request" },
- { 0x0F, "Move Channel Response" },
- { 0x10, "Move Channel Confirmation" },
- { 0x11, "Move Channel Confirmation Response" },
- { 0, NULL }
+ { 0x01, "Command Reject" },
+ { 0x02, "Connection Request" },
+ { 0x03, "Connection Response" },
+ { 0x04, "Configure Request" },
+ { 0x05, "Configure Response" },
+ { 0x06, "Disconnect Request" },
+ { 0x07, "Disconnect Response" },
+ { 0x08, "Echo Request" },
+ { 0x09, "Echo Response" },
+ { 0x0A, "Information Request" },
+ { 0x0B, "Information Response" },
+ { 0x0C, "Create Channel Request" },
+ { 0x0D, "Create Channel Response" },
+ { 0x0E, "Move Channel Request" },
+ { 0x0F, "Move Channel Response" },
+ { 0x10, "Move Channel Confirmation" },
+ { 0x11, "Move Channel Confirmation Response" },
+ { 0, NULL }
};
static const value_string psm_vals[] = {
- { 0x0001, "SDP" },
- { 0x0003, "RFCOMM" },
- { 0x0005, "TCS-BIN" },
- { 0x0007, "TCS-BIN-CORDLESS" },
- { 0x000F, "BNEP" },
- { 0x0011, "HID-Control" },
- { 0x0013, "HID-Interrupt" },
- { 0x0015, "UPnP" },
- { 0x0017, "AVCTP-Control" },
- { 0x0019, "AVDTP" },
- { 0x001B, "AVCTP-Browsing" },
- { 0x001D, "UDI_C-Plane" },
- { 0, NULL }
+ { 0x0001, "SDP" },
+ { 0x0003, "RFCOMM" },
+ { 0x0005, "TCS-BIN" },
+ { 0x0007, "TCS-BIN-CORDLESS" },
+ { 0x000F, "BNEP" },
+ { 0x0011, "HID-Control" },
+ { 0x0013, "HID-Interrupt" },
+ { 0x0015, "UPnP" },
+ { 0x0017, "AVCTP-Control" },
+ { 0x0019, "AVDTP" },
+ { 0x001B, "AVCTP-Browsing" },
+ { 0x001D, "UDI_C-Plane" },
+ { 0, NULL }
};
static const value_string result_vals[] = {
- { 0x0000, "Successful" },
- { 0x0001, "Pending" },
- { 0x0002, "Refused - PSM not supported" },
- { 0x0003, "Refused - security block" },
- { 0x0004, "Refused - no resources available" },
- { 0x0005, "Refused - Controller ID not supported" },
- { 0, NULL }
+ { 0x0000, "Successful" },
+ { 0x0001, "Pending" },
+ { 0x0002, "Refused - PSM not supported" },
+ { 0x0003, "Refused - security block" },
+ { 0x0004, "Refused - no resources available" },
+ { 0x0005, "Refused - Controller ID not supported" },
+ { 0, NULL }
};
static const value_string move_result_vals[] = {
- { 0x0000, "Success" },
- { 0x0001, "Pending" },
- { 0x0002, "Refused - Controller ID not supported" },
- { 0x0003, "Refused - New Controller ID is same as old" },
- { 0x0004, "Refused - Configuration not supported" },
- { 0x0005, "Refused - Move Channel collision" },
- { 0x0006, "Refused - Channel not allowed to be moved" },
- { 0, NULL }
+ { 0x0000, "Success" },
+ { 0x0001, "Pending" },
+ { 0x0002, "Refused - Controller ID not supported" },
+ { 0x0003, "Refused - New Controller ID is same as old" },
+ { 0x0004, "Refused - Configuration not supported" },
+ { 0x0005, "Refused - Move Channel collision" },
+ { 0x0006, "Refused - Channel not allowed to be moved" },
+ { 0, NULL }
};
static const value_string move_result_confirmation_vals[] = {
- { 0x0000, "Success - both sides succeed" },
- { 0x0001, "Failure - one or both sides refuse" },
- { 0, NULL }
+ { 0x0000, "Success - both sides succeed" },
+ { 0x0001, "Failure - one or both sides refuse" },
+ { 0, NULL }
};
static const value_string configuration_result_vals[] = {
- { 0x0000, "Success"},
- { 0x0001, "Failure - unacceptable parameters" },
- { 0x0002, "Failure - reject (no reason provided)" },
- { 0x0003, "Failure - unknown options" },
- { 0x0004, "Pending" },
- { 0x0005, "Failure - flow spec rejected" },
- { 0, NULL }
+ { 0x0000, "Success"},
+ { 0x0001, "Failure - unacceptable parameters" },
+ { 0x0002, "Failure - reject (no reason provided)" },
+ { 0x0003, "Failure - unknown options" },
+ { 0x0004, "Pending" },
+ { 0x0005, "Failure - flow spec rejected" },
+ { 0, NULL }
};
static const value_string status_vals[] = {
- { 0x0000, "No further information available" },
- { 0x0001, "Authentication pending" },
- { 0x0002, "Authorization pending" },
- { 0, NULL }
+ { 0x0000, "No further information available" },
+ { 0x0001, "Authentication pending" },
+ { 0x0002, "Authorization pending" },
+ { 0, NULL }
};
static const value_string reason_vals[] = {
- { 0x0000, "Command not understood" },
- { 0x0001, "Signaling MTU exceeded" },
- { 0x0002, "Invalid CID in request" },
- { 0, NULL }
+ { 0x0000, "Command not understood" },
+ { 0x0001, "Signaling MTU exceeded" },
+ { 0x0002, "Invalid CID in request" },
+ { 0, NULL }
};
static const value_string info_type_vals[] = {
- { 0x0001, "Connectionless MTU" },
- { 0x0002, "Extended Features Mask" },
- { 0x0003, "Fixed Channels Supported" },
- { 0, NULL }
+ { 0x0001, "Connectionless MTU" },
+ { 0x0002, "Extended Features Mask" },
+ { 0x0003, "Fixed Channels Supported" },
+ { 0, NULL }
};
static const value_string info_result_vals[] = {
- { 0x0000, "Success" },
- { 0x0001, "Not Supported" },
- { 0, NULL }
+ { 0x0000, "Success" },
+ { 0x0001, "Not Supported" },
+ { 0, NULL }
};
static const value_string option_servicetype_vals[] = {
- { 0x00, "No traffic" },
- { 0x01, "Best effort (Default)" },
- { 0x02, "Guaranteed" },
- { 0, NULL }
+ { 0x00, "No traffic" },
+ { 0x01, "Best effort (Default)" },
+ { 0x02, "Guaranteed" },
+ { 0, NULL }
};
static const value_string option_type_vals[] = {
- { 0x01, "Maximum Transmission Unit" },
- { 0x02, "Flush Timeout" },
- { 0x03, "Quality of Service" },
- { 0x04, "Retransmission and Flow Control" },
- { 0x05, "FCS" },
- { 0x06, "Extended Flow Specification" },
- { 0x07, "Extended Window Size" },
- { 0, NULL }
+ { 0x01, "Maximum Transmission Unit" },
+ { 0x02, "Flush Timeout" },
+ { 0x03, "Quality of Service" },
+ { 0x04, "Retransmission and Flow Control" },
+ { 0x05, "FCS" },
+ { 0x06, "Extended Flow Specification" },
+ { 0x07, "Extended Window Size" },
+ { 0, NULL }
};
static const value_string option_retransmissionmode_vals[] = {
- { 0x00, "Basic Mode" },
- { 0x01, "Retransmission Mode" },
- { 0x02, "Flow Control Mode" },
- { 0x03, "Enhanced Retransmission Mode" },
- { 0x04, "Streaming Mode" },
- { 0, NULL }
+ { 0x00, "Basic Mode" },
+ { 0x01, "Retransmission Mode" },
+ { 0x02, "Flow Control Mode" },
+ { 0x03, "Enhanced Retransmission Mode" },
+ { 0x04, "Streaming Mode" },
+ { 0, NULL }
};
static const value_string control_sar_vals[] = {
- { 0x00, "Unsegmented" },
- { 0x01, "Start" },
- { 0x02, "End" },
- { 0x03, "Continuation" },
- { 0, NULL }
+ { 0x00, "Unsegmented" },
+ { 0x01, "Start" },
+ { 0x02, "End" },
+ { 0x03, "Continuation" },
+ { 0, NULL }
};
static const value_string control_supervisory_vals[] = {
- { 0x00, "RR" },
- { 0x01, "REJ" },
- { 0x02, "RNR" },
- { 0x03, "SREJ" },
- { 0, NULL }
+ { 0x00, "RR" },
+ { 0x01, "REJ" },
+ { 0x02, "RNR" },
+ { 0x03, "SREJ" },
+ { 0, NULL }
};
static const value_string control_type_vals[] = {
- { 0x00, "I-Frame" },
- { 0x01, "S-Frame" },
- { 0, NULL }
+ { 0x00, "I-Frame" },
+ { 0x01, "S-Frame" },
+ { 0, NULL }
};
static const value_string option_fcs_vals[] = {
- { 0x00, "No FCS" },
- { 0x01, "16-bit FCS" },
- { 0, NULL }
+ { 0x00, "No FCS" },
+ { 0x01, "16-bit FCS" },
+ { 0, NULL }
};
static const value_string ctrl_id_code_vals[] = {
- { 0x00, "Bluetooth BR/EDR" },
- { 0x01, "Wifi 802.11" },
- { 0, NULL }
+ { 0x00, "Bluetooth BR/EDR" },
+ { 0x01, "Wifi 802.11" },
+ { 0, NULL }
};
static int
dissect_comrej(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 reason;
+ guint16 reason;
- reason = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_rej_reason, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ reason = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_rej_reason, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- switch(reason){
- case 0x0000: /* Command not understood */
- break;
+ switch (reason) {
+ case 0x0000: /* Command not understood */
+ break;
- case 0x0001: /* Signaling MTU exceeded */
- proto_tree_add_item(tree, hf_btl2cap_sig_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
- break;
+ case 0x0001: /* Signaling MTU exceeded */
+ proto_tree_add_item(tree, hf_btl2cap_sig_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ break;
- case 0x0002: /* Invalid CID in requets */
- proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ case 0x0002: /* Invalid CID in requets */
+ proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- break;
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- return offset;
+ return offset;
}
static int
dissect_connrequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, gboolean is_ch_request)
{
- guint16 scid, psm;
- psm_data_t *psm_data;
- const gchar *psm_str = "<NONE>";
-
- psm=tvb_get_letohs(tvb, offset);
- if( psm < BTL2CAP_DYNAMIC_PSM_START ) {
- proto_tree_add_item(tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- psm_str = val_to_str(psm, psm_vals, "Unknown PSM");
- }
- else {
- guint32 *service, token;
- proto_item *item;
-
- item = proto_tree_add_item(tree, hf_btl2cap_psm_dynamic, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- token = psm | ((pinfo->p2p_dir == P2P_DIR_RECV)?0x80000000:0x00000000);
- service = se_tree_lookup32(psm_to_service_table, token);
-
- if( service ) {
- psm_str = val_to_str(*service, vs_service_classes, "Unknown PSM");
- proto_item_append_text(item," (%s)", psm_str);
- }
- }
- offset+=2;
-
- scid=tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- if( psm_str )
- col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, SCID: 0x%04x)", psm_str, scid);
- else
- col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x)", scid);
-
- if( is_ch_request ) {
- proto_tree_add_item(tree, hf_btl2cap_controller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset+=1;
- }
-
- if (pinfo->fd->flags.visited == 0) {
- emem_tree_key_t key[3];
- guint32 kcid;
- guint32 frame_number;
-
- psm_data=se_alloc(sizeof(psm_data_t));
- psm_data->scid = (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000));
- psm_data->dcid = 0;
- psm_data->psm=psm;
- psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? TRUE : FALSE;
- psm_data->in.mode=0;
- psm_data->in.txwindow=0;
- psm_data->in.start_fragments=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_l2cap fragment starts");
- psm_data->out.mode=0;
- psm_data->out.txwindow=0;
- psm_data->out.start_fragments=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_l2cap fragment starts");
-
- frame_number = pinfo->fd->num;
- kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
-
- se_tree_insert32_array(cid_to_psm_table, key, psm_data);
- }
- return offset;
+ guint16 scid, psm;
+ psm_data_t *psm_data;
+ const gchar *psm_str = "<NONE>";
+
+ psm = tvb_get_letohs(tvb, offset);
+ if (psm < BTL2CAP_DYNAMIC_PSM_START) {
+ proto_tree_add_item(tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ psm_str = val_to_str_const(psm, psm_vals, "Unknown PSM");
+ }
+ else {
+ guint32 *service, token;
+ proto_item *item;
+
+ item = proto_tree_add_item(tree, hf_btl2cap_psm_dynamic, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ token = psm | ((pinfo->p2p_dir == P2P_DIR_RECV)?0x80000000:0x00000000);
+ service = se_tree_lookup32(psm_to_service_table, token);
+
+ if (service) {
+ psm_str = val_to_str_ext_const(*service, &vs_service_classes_ext, "Unknown PSM");
+ proto_item_append_text(item," (%s)", psm_str);
+ }
+ }
+ offset += 2;
+
+ scid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ if (psm_str)
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, SCID: 0x%04x)", psm_str, scid);
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x)", scid);
+
+ if (is_ch_request) {
+ proto_tree_add_item(tree, hf_btl2cap_controller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+
+ if (!pinfo->fd->flags.visited) {
+ emem_tree_key_t key[3];
+ guint32 kcid;
+ guint32 frame_number;
+
+ /* XXX: Is using 0x8000 OK ? scid appears to be 16 bits */
+ psm_data = se_alloc(sizeof(psm_data_t));
+ psm_data->scid = (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000));
+ psm_data->dcid = 0;
+ psm_data->psm = psm;
+ psm_data->local_service = (pinfo->p2p_dir == P2P_DIR_RECV) ? TRUE : FALSE;
+ psm_data->in.mode = 0;
+ psm_data->in.txwindow = 0;
+ psm_data->in.start_fragments = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_l2cap fragment starts");
+ psm_data->out.mode = 0;
+ psm_data->out.txwindow = 0;
+ psm_data->out.start_fragments = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "bthci_l2cap fragment starts");
+
+ frame_number = pinfo->fd->num;
+ kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+
+ se_tree_insert32_array(cid_to_psm_table, key, psm_data);
+ }
+ return offset;
}
static int
dissect_movechanrequest(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 icid;
- guint8 ctrl_id;
+ guint16 icid;
+ guint8 ctrl_id;
- icid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ icid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- ctrl_id = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_dcontroller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset+=1;
+ ctrl_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_dcontroller, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, move to %s)", icid, val_to_str(ctrl_id, ctrl_id_code_vals, "Unknown controller"));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, move to %s)", icid,
+ val_to_str_const(ctrl_id, ctrl_id_code_vals, "Unknown controller"));
- return offset;
+ return offset;
}
static int
dissect_options(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int length, config_data_t *config_data)
{
- proto_item *ti_option=NULL;
- proto_tree *ti_option_subtree=NULL;
- guint8 option_type, option_length;
+ proto_item *ti_option;
+ proto_tree *ti_option_subtree;
+ guint8 option_type, option_length;
- while(length>0){
- option_type = tvb_get_guint8(tvb, offset);
- option_length = tvb_get_guint8(tvb, offset+1);
+ while (length > 0) {
+ option_type = tvb_get_guint8(tvb, offset);
+ option_length = tvb_get_guint8(tvb, offset+1);
- ti_option = proto_tree_add_none_format(tree,
- hf_btl2cap_option, tvb,
- offset, option_length + 2,
- "Option: ");
- ti_option_subtree = proto_item_add_subtree(ti_option, ett_btl2cap_option);
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_length, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
- offset+=2;
+ ti_option = proto_tree_add_none_format(tree,
+ hf_btl2cap_option, tvb,
+ offset, option_length + 2,
+ "Option: ");
+ ti_option_subtree = proto_item_add_subtree(ti_option, ett_btl2cap_option);
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_length, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
+ offset += 2;
- if(option_length>0){
- switch(option_type){
- case 0x01: /* MTU */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ if (option_length != 0) {
+ switch (option_type) {
+ case 0x01: /* MTU */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_item_append_text(ti_option, "MTU");
- break;
+ proto_item_append_text(ti_option, "MTU");
+ break;
- case 0x02: /* Flush timeout */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flushTO, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ case 0x02: /* Flush timeout */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flushTO, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_item_append_text(ti_option, "Flush Timeout");
- break;
+ proto_item_append_text(ti_option, "Flush Timeout");
+ break;
- case 0x03: /* QOS */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ case 0x03: /* QOS */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenrate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenbucketsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_tokenbucketsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_peakbandwidth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_peakbandwidth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_delayvariation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_delayvariation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_item_append_text(ti_option, "QOS");
- break;
+ proto_item_append_text(ti_option, "QOS");
+ break;
- case 0x04: /* Retransmission and Flow Control*/
- if(config_data)
- {
- config_data->mode = tvb_get_guint8(tvb, offset);
- config_data->txwindow = tvb_get_guint8(tvb, offset+1);
- }
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmissionmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ case 0x04: /* Retransmission and Flow Control*/
+ if (config_data)
+ {
+ config_data->mode = tvb_get_guint8(tvb, offset);
+ config_data->txwindow = tvb_get_guint8(tvb, offset+1);
+ }
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmissionmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_txwindow, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_txwindow, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_maxtransmit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_maxtransmit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmittimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+= 2;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_retransmittimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_monitortimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+= 2;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_monitortimeout, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+= 2;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_mps, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_item_append_text(ti_option, "Retransmission and Flow Control");
- break;
+ proto_item_append_text(ti_option, "Retransmission and Flow Control");
+ break;
- case 0x05: /* FCS */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_fcs, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset+=1;
+ case 0x05: /* FCS */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_fcs, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_item_append_text(ti_option, "FCS");
- break;
+ proto_item_append_text(ti_option, "FCS");
+ break;
- case 0x06: /* Extended Flow Specification */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_identifier, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ case 0x06: /* Extended Flow Specification */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_identifier, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_service_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_arrival_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_sdu_arrival_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_access_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_access_latency, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flush_to_us, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_flush_to_us, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- proto_item_append_text(ti_option, "Extended Flow Specification");
- break;
+ proto_item_append_text(ti_option, "Extended Flow Specification");
+ break;
- case 0x07: /* Extended Window Size */
- proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_window, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ case 0x07: /* Extended Window Size */
+ proto_tree_add_item(ti_option_subtree, hf_btl2cap_option_window, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- proto_item_append_text(ti_option, "Extended Window Size");
- break;
+ proto_item_append_text(ti_option, "Extended Window Size");
+ break;
- default:
- proto_item_append_text(ti_option, "unknown");
- offset+=option_length;
- break;
- }
- }
- length -= (option_length + 2);
- }
- return offset;
+ default:
+ proto_item_append_text(ti_option, "unknown");
+ offset += option_length;
+ break;
+ }
+ }
+ length -= (option_length + 2);
+ }
+ return offset;
}
@@ -590,565 +593,574 @@ dissect_options(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *t
static int
dissect_configrequest(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint16 length)
{
- psm_data_t *psm_data;
- config_data_t *config_data;
- guint16 dcid;
- emem_tree_key_t key[3];
- guint32 kcid;
- guint32 frame_number;
-
- dcid = tvb_get_letohs(tvb, offset);
-
- frame_number = pinfo->fd->num;
- kcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
-
- psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
-
- proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " (DCID: 0x%04x)", dcid);
-
- proto_tree_add_item(tree, hf_btl2cap_continuation_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- if(tvb_length_remaining(tvb, offset)){
- if (psm_data && psm_data->dcid == (dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)))
- if(pinfo->p2p_dir==P2P_DIR_RECV)
- config_data = &(psm_data->out);
- else
- config_data = &(psm_data->in);
- else
- config_data = NULL;
- offset=dissect_options(tvb, offset, pinfo, tree, length - 4, config_data);
- }
-
- return offset;
+ psm_data_t *psm_data;
+ config_data_t *config_data;
+ guint16 dcid;
+ emem_tree_key_t key[3];
+ guint32 kcid;
+ guint32 frame_number;
+
+ dcid = tvb_get_letohs(tvb, offset);
+
+ frame_number = pinfo->fd->num;
+ kcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+
+ psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
+
+ proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (DCID: 0x%04x)", dcid);
+
+ proto_tree_add_item(tree, hf_btl2cap_continuation_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if (psm_data && psm_data->dcid == (dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)))
+ if (pinfo->p2p_dir == P2P_DIR_RECV)
+ config_data = &(psm_data->out);
+ else
+ config_data = &(psm_data->in);
+ else
+ config_data = NULL;
+ offset = dissect_options(tvb, offset, pinfo, tree, length - 4, config_data);
+ }
+
+ return offset;
}
static int
dissect_inforequest(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 info_type;
+ guint16 info_type;
- info_type=tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ info_type = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(info_type, info_type_vals, "Unknown type"));
- return offset;
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(info_type, info_type_vals, "Unknown type"));
+ return offset;
}
static int
dissect_inforesponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 info_type, result;
- proto_item *ti_features=NULL;
- proto_tree *ti_features_subtree=NULL;
- guint32 features;
-
- info_type=tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- result = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_info_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, %s)",
- val_to_str(info_type, info_type_vals, "Unknown type"),
- val_to_str(result, info_result_vals, "Unknown result"));
-
- if(tvb_length_remaining(tvb, offset)) {
- switch(info_type){
- case 0x0001: /* Connectionless MTU */
- proto_tree_add_item(tree, hf_btl2cap_info_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- break;
- case 0x0002: /* Extended Features */
- ti_features = proto_tree_add_none_format(tree,
- hf_btl2cap_info_extfeatures, tvb,
- offset, 4,
- "Features: ");
- ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_extfeatures);
- features = tvb_get_letohl(tvb, offset);
- if(features & 0x1)
- proto_item_append_text(ti_features, "FlowControl ");
- if(features & 0x2)
- proto_item_append_text(ti_features, "Retransmission ");
- if(features & 0x4)
- proto_item_append_text(ti_features, "BiDirQOS ");
- if(features & 0x8)
- proto_item_append_text(ti_features, "EnhRetransmission ");
- if(features & 0x10)
- proto_item_append_text(ti_features, "Streaming ");
- if(features & 0x20)
- proto_item_append_text(ti_features, "FCS ");
- if(features & 0x40)
- proto_item_append_text(ti_features, "FlowSpec ");
- if(features & 0x80)
- proto_item_append_text(ti_features, "FixedChan ");
- if(features & 0x100)
- proto_item_append_text(ti_features, "WindowSize ");
- if(features & 0x200)
- proto_item_append_text(ti_features, "Unicast ");
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flowcontrol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_retransmission, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_bidirqos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_enh_retransmission, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_streaming, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fcs, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flow_spec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchan, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_window, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_unicast, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
-
- break;
-
- case 0x0003: /* Fixed Channels Supported */
- ti_features = proto_tree_add_none_format(tree,
- hf_btl2cap_info_fixedchans, tvb,
- offset, 8,
- "Fixed Channels Supported:");
- ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_fixedchans);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_null, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_connless, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_man, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
- proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_test, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset+=4;
-
- break;
-
- default:
- proto_tree_add_item(tree, hf_btl2cap_cmd_data, tvb, offset, -1, ENC_NA);
- offset+=tvb_length_remaining(tvb, offset);
-
- break;
- }
- }
-
- return offset;
+ guint16 info_type, result;
+
+ info_type = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_info_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ result = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_info_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s, %s)",
+ val_to_str_const(info_type, info_type_vals, "Unknown type"),
+ val_to_str_const(result, info_result_vals, "Unknown result"));
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_item *ti_features;
+ proto_tree *ti_features_subtree;
+ guint32 features;
+
+ switch (info_type) {
+ case 0x0001: /* Connectionless MTU */
+ proto_tree_add_item(tree, hf_btl2cap_info_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ break;
+ case 0x0002: /* Extended Features */
+ ti_features = proto_tree_add_none_format(tree,
+ hf_btl2cap_info_extfeatures, tvb,
+ offset, 4,
+ "Features: ");
+ ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_extfeatures);
+ features = tvb_get_letohl(tvb, offset);
+ if (features & 0x1)
+ proto_item_append_text(ti_features, "FlowControl ");
+ if (features & 0x2)
+ proto_item_append_text(ti_features, "Retransmission ");
+ if (features & 0x4)
+ proto_item_append_text(ti_features, "BiDirQOS ");
+ if (features & 0x8)
+ proto_item_append_text(ti_features, "EnhRetransmission ");
+ if (features & 0x10)
+ proto_item_append_text(ti_features, "Streaming ");
+ if (features & 0x20)
+ proto_item_append_text(ti_features, "FCS ");
+ if (features & 0x40)
+ proto_item_append_text(ti_features, "FlowSpec ");
+ if (features & 0x80)
+ proto_item_append_text(ti_features, "FixedChan ");
+ if (features & 0x100)
+ proto_item_append_text(ti_features, "WindowSize ");
+ if (features & 0x200)
+ proto_item_append_text(ti_features, "Unicast ");
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flowcontrol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_retransmission, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_bidirqos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_enh_retransmission, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_streaming, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fcs, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_flow_spec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchan, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_window, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_unicast, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ break;
+
+ case 0x0003: /* Fixed Channels Supported */
+ ti_features = proto_tree_add_none_format(tree,
+ hf_btl2cap_info_fixedchans, tvb,
+ offset, 8,
+ "Fixed Channels Supported:");
+ ti_features_subtree = proto_item_add_subtree(ti_features, ett_btl2cap_fixedchans);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_null, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_connless, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_man, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(ti_features_subtree, hf_btl2cap_info_fixedchans_amp_test, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ break;
+
+ default:
+ proto_tree_add_item(tree, hf_btl2cap_cmd_data, tvb, offset, -1, ENC_NA);
+ offset += tvb_reported_length_remaining(tvb, offset);
+
+ break;
+ }
+ }
+
+ return offset;
}
static int
dissect_configresponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint16 length)
{
- psm_data_t *psm_data;
- config_data_t *config_data;
- guint16 scid, result;
- emem_tree_key_t key[3];
- guint32 kcid;
- guint32 frame_number;
-
- scid = tvb_get_letohs(tvb, offset);
-
- frame_number = pinfo->fd->num;
- kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
-
- psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
-
- proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- proto_tree_add_item(tree, hf_btl2cap_continuation_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- result = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_configuration_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)", val_to_str(result, configuration_result_vals, "Unknown"), scid);
-
- if(tvb_length_remaining(tvb, offset)){
- if (psm_data && psm_data->scid == (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)))
- if(pinfo->p2p_dir==P2P_DIR_RECV)
- config_data = &(psm_data->out);
- else
- config_data = &(psm_data->in);
- else
- config_data = NULL;
- offset=dissect_options(tvb, offset, pinfo, tree, length - 6, config_data);
- }
-
- return offset;
+ psm_data_t *psm_data;
+ config_data_t *config_data;
+ guint16 scid, result;
+ emem_tree_key_t key[3];
+ guint32 kcid;
+ guint32 frame_number;
+
+ scid = tvb_get_letohs(tvb, offset);
+
+ frame_number = pinfo->fd->num;
+ kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+
+ psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
+
+ proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_btl2cap_continuation_flag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ result = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_configuration_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
+ val_to_str_const(result, configuration_result_vals, "Unknown"), scid);
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if (psm_data && psm_data->scid == (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)))
+ if (pinfo->p2p_dir == P2P_DIR_RECV)
+ config_data = &(psm_data->out);
+ else
+ config_data = &(psm_data->in);
+ else
+ config_data = NULL;
+ offset = dissect_options(tvb, offset, pinfo, tree, length - 6, config_data);
+ }
+
+ return offset;
}
static int
dissect_connresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
- guint16 scid, dcid, result;
- psm_data_t *psm_data;
- emem_tree_key_t key[3];
- guint32 kcid;
- guint32 frame_number;
-
- dcid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- scid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- result = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- proto_tree_add_item(tree, hf_btl2cap_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- if(!result) {
- col_append_fstr(pinfo->cinfo, COL_INFO, " - Success (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
- }
- else {
- col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)", val_to_str(result, result_vals, "Unknown"), scid);
- }
-
- if (pinfo->fd->flags.visited == 0) {
- frame_number = pinfo->fd->num;
- kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
-
- psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
-
- if (psm_data && psm_data->scid == (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000))) {
- frame_number = pinfo->fd->num;
- kcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
- psm_data->dcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
-
- se_tree_insert32_array(cid_to_psm_table, key, psm_data);
- }
- }
-
- return offset;
+ guint16 scid, dcid, result;
+ psm_data_t *psm_data;
+ emem_tree_key_t key[3];
+ guint32 kcid;
+ guint32 frame_number;
+
+ dcid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ scid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ result = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_btl2cap_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ if (result == 0) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " - Success (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
+ }
+ else {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " - %s (SCID: 0x%04x)",
+ val_to_str_const(result, result_vals, "Unknown"), scid);
+ }
+
+ if (pinfo->fd->flags.visited == 0) {
+ frame_number = pinfo->fd->num;
+ kcid = scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+
+ psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
+
+ if (psm_data && psm_data->scid == (scid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000))) {
+ frame_number = pinfo->fd->num;
+ kcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+ psm_data->dcid = dcid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x8000 : 0x0000);
+
+ se_tree_insert32_array(cid_to_psm_table, key, psm_data);
+ }
+ }
+
+ return offset;
}
static int
dissect_chanresponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
- return dissect_connresponse(tvb, offset, pinfo, tree);
+ return dissect_connresponse(tvb, offset, pinfo, tree);
}
static int
dissect_movechanresponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 icid, result;
+ guint16 icid, result;
- icid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ icid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- result = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_move_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ result = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_move_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid, val_to_str(result, move_result_vals, "Unknown result"));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
+ val_to_str_const(result, move_result_vals, "Unknown result"));
- return offset;
+ return offset;
}
static int
dissect_movechanconfirmation(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 icid, result;
+ guint16 icid, result;
- icid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ icid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- result = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_move_confirmation_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ result = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_move_confirmation_result, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid, val_to_str(result, move_result_confirmation_vals, "Unknown result"));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x, %s)", icid,
+ val_to_str_const(result, move_result_confirmation_vals, "Unknown result"));
- return offset;
+ return offset;
}
static int
dissect_movechanconfirmationresponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 icid;
+ guint16 icid;
- icid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ icid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_icid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x)", icid);
- return offset;
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (ICID: 0x%04x)", icid);
+ return offset;
}
static int
dissect_disconnrequestresponse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
{
- guint16 scid, dcid;
+ guint16 scid, dcid;
- dcid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ dcid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_dcid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- scid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
+ scid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_btl2cap_scid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (SCID: 0x%04x, DCID: 0x%04x)", scid, dcid);
- return offset;
+ return offset;
}
static int
-dissect_b_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *btl2cap_tree, guint16 psm, gboolean local_service, guint16 length, int offset)
+dissect_b_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *btl2cap_tree,
+ guint16 psm, gboolean local_service, guint16 length, int offset)
{
- tvbuff_t *next_tvb;
- next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
-
- col_append_str(pinfo->cinfo, COL_INFO, "Connection oriented channel");
-
- if(psm){
- proto_item *psm_item;
- guint32 *service =se_tree_lookup32(psm_to_service_table, (local_service<<31) | psm);
-
- if( psm < BTL2CAP_DYNAMIC_PSM_START ) {
- psm_item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
- }
- else {
- psm_item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
- if( service )
- proto_item_append_text(psm_item,": %s", val_to_str(*service, vs_service_classes, "Unknown service"));
- }
- PROTO_ITEM_SET_GENERATED(psm_item);
-
- /* call next dissector */
- if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
- /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
- if(service != NULL && !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
- /* unknown protocol. declare as data */
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
- }
- }
- offset+=tvb_length_remaining(tvb, offset);
- }
- else {
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
- offset+=tvb_length_remaining(tvb, offset);
- }
- return offset;
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
+
+ col_append_str(pinfo->cinfo, COL_INFO, "Connection oriented channel");
+
+ if (psm) {
+ proto_item *psm_item;
+ guint32 *service = se_tree_lookup32(psm_to_service_table, (local_service<<31) | psm);
+
+ if (psm < BTL2CAP_DYNAMIC_PSM_START) {
+ psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
+ }
+ else {
+ psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
+ if (service)
+ proto_item_append_text(psm_item,": %s",
+ val_to_str_ext_const(*service, &vs_service_classes_ext, "Unknown service"));
+ }
+ PROTO_ITEM_SET_GENERATED(psm_item);
+
+ /* call next dissector */
+ if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
+ /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
+ if ((service == NULL) || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
+ /* unknown protocol. declare as data */
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
+ }
+ }
+ offset += tvb_length_remaining(tvb, offset);
+ }
+ else {
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
+ offset += tvb_length_remaining(tvb, offset);
+ }
+ return offset;
}
typedef struct _sdu_reassembly_t
{
- guint8* reassembled;
- guint8 seq;
- guint32 first_frame;
- guint32 last_frame;
- guint16 tot_len;
- int cur_off; /* counter used by reassembly */
+ guint8 *reassembled;
+ guint8 seq;
+ guint32 first_frame;
+ guint32 last_frame;
+ guint16 tot_len;
+ int cur_off; /* counter used by reassembly */
} sdu_reassembly_t;
static int
-dissect_i_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *btl2cap_tree, psm_data_t *psm_data, guint16 length, int offset, config_data_t *config_data)
+dissect_i_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *btl2cap_tree,
+ psm_data_t *psm_data, guint16 length, int offset, config_data_t *config_data)
{
- tvbuff_t *next_tvb = NULL;
- guint16 control, segment;
- guint16 sdulen;
- proto_item* ti_control;
- proto_tree* ti_control_subtree;
- sdu_reassembly_t* mfp = NULL;
- guint16 psm = (psm_data?psm_data->psm:0);
-
- control = tvb_get_letohs(tvb, offset);
- segment = (control & 0xC000) >> 14;
- switch(segment)
- {
- case 0:
- col_append_str(pinfo->cinfo, COL_INFO, "[I] Unsegmented SDU");
- break;
- case 1:
- col_append_str(pinfo->cinfo, COL_INFO, "[I] Start SDU");
- break;
- case 2:
- col_append_str(pinfo->cinfo, COL_INFO, "[I] End SDU");
- break;
- case 3:
- col_append_str(pinfo->cinfo, COL_INFO, "[I] Continuation SDU");
- break;
- }
- ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
- offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
- val_to_str((control & 0xC000) >> 14, control_sar_vals, "unknown"),
- (control & 0x3F00) >> 8,
- (control & 0x0080) >> 7,
- (control & 0x007E) >> 1);
- ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
-
- /*Segmented frames with SAR = start have an extra SDU length header field*/
- if(segment == 0x01) {
- proto_item *pi;
- sdulen = tvb_get_letohs(tvb, offset);
- pi = proto_tree_add_item(btl2cap_tree, hf_btl2cap_sdulength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- length -= 6; /*Control, SDUlength, FCS*/
-
- /* Detect malformed data */
- if (sdulen < length) {
- sdulen = length;
- expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN,
- "SDU length less than length of first packet");
- }
-
- if(!pinfo->fd->flags.visited){
- mfp=se_alloc(sizeof(sdu_reassembly_t));
- mfp->first_frame=pinfo->fd->num;
- mfp->last_frame=0;
- mfp->tot_len=sdulen;
- mfp->reassembled=se_alloc(sdulen);
- tvb_memcpy(tvb, mfp->reassembled, offset, length);
- mfp->cur_off=length;
- se_tree_insert32(config_data->start_fragments, pinfo->fd->num, mfp);
- } else {
- mfp=se_tree_lookup32(config_data->start_fragments, pinfo->fd->num);
- }
- if(mfp != NULL && mfp->last_frame){
- proto_item *item;
- item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_reassembled_in, tvb, 0, 0, mfp->last_frame);
- PROTO_ITEM_SET_GENERATED(item);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembled in #%u] ", mfp->last_frame);
- }
- } else {
- length -= 4; /*Control, FCS*/
- }
- if(segment == 0x02 || segment == 0x03) {
- mfp=se_tree_lookup32_le(config_data->start_fragments, pinfo->fd->num);
- if(!pinfo->fd->flags.visited){
- if(mfp != NULL && !mfp->last_frame && (mfp->tot_len>=mfp->cur_off+length)){
- tvb_memcpy(tvb, mfp->reassembled+mfp->cur_off, offset, length);
- mfp->cur_off+=length;
- if(segment == 0x02){
- mfp->last_frame=pinfo->fd->num;
- }
- }
- }
- if(mfp){
- proto_item *item;
- item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_continuation_to, tvb, 0, 0, mfp->first_frame);
- PROTO_ITEM_SET_GENERATED(item);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", mfp->first_frame);
- }
- }
- if(segment == 0x02 && mfp != NULL && mfp->last_frame==pinfo->fd->num){
- next_tvb = tvb_new_child_real_data(tvb, (guint8*)mfp->reassembled, mfp->tot_len, mfp->tot_len);
- add_new_data_source(pinfo, next_tvb, "Reassembled L2CAP");
- }
- /*pass up to higher layer if we have a complete packet*/
- if(segment == 0x00) {
- next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset) - 2, length);
- }
- if(next_tvb) {
- if(psm){
- guint32 *service =se_tree_lookup32(psm_to_service_table, ((psm_data?psm_data->local_service:0)<<31) | psm);
- proto_item *psm_item;
-
- if( psm < BTL2CAP_DYNAMIC_PSM_START ) {
- psm_item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
- }
- else {
- psm_item=proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
- if(service)
- proto_item_append_text(psm_item," (%s)", val_to_str(*service, vs_service_classes, "Unknown service"));
- }
- PROTO_ITEM_SET_GENERATED(psm_item);
-
- /* call next dissector */
- if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
- /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
- if(service != NULL && !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
- /* unknown protocol. declare as data */
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_length(next_tvb), ENC_NA);
- }
- }
- }
- else {
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_length(next_tvb), ENC_NA);
- }
- }
- offset+=(tvb_length_remaining(tvb, offset) - 2);
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- return offset;
+ tvbuff_t *next_tvb = NULL;
+ guint16 control, segment;
+ guint16 sdulen;
+ proto_item* ti_control;
+ proto_tree* ti_control_subtree;
+ sdu_reassembly_t *mfp = NULL;
+ guint16 psm = (psm_data?psm_data->psm:0);
+
+ control = tvb_get_letohs(tvb, offset);
+ segment = (control & 0xC000) >> 14;
+ switch (segment) {
+ case 0:
+ col_append_str(pinfo->cinfo, COL_INFO, "[I] Unsegmented SDU");
+ break;
+ case 1:
+ col_append_str(pinfo->cinfo, COL_INFO, "[I] Start SDU");
+ break;
+ case 2:
+ col_append_str(pinfo->cinfo, COL_INFO, "[I] End SDU");
+ break;
+ case 3:
+ col_append_str(pinfo->cinfo, COL_INFO, "[I] Continuation SDU");
+ break;
+ }
+ ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
+ offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
+ val_to_str_const((control & 0xC000) >> 14, control_sar_vals, "unknown"),
+ (control & 0x3F00) >> 8,
+ (control & 0x0080) >> 7,
+ (control & 0x007E) >> 1);
+ ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /*Segmented frames with SAR = start have an extra SDU length header field*/
+ if (segment == 0x01) {
+ proto_item *pi;
+ sdulen = tvb_get_letohs(tvb, offset);
+ pi = proto_tree_add_item(btl2cap_tree, hf_btl2cap_sdulength, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ length -= 6; /*Control, SDUlength, FCS*/
+
+ /* Detect malformed data */
+ if (sdulen < length) {
+ sdulen = length;
+ expert_add_info_format(pinfo, pi, PI_MALFORMED, PI_WARN,
+ "SDU length less than length of first packet");
+ }
+
+ if (!pinfo->fd->flags.visited) {
+ mfp = se_alloc(sizeof(sdu_reassembly_t));
+ mfp->first_frame = pinfo->fd->num;
+ mfp->last_frame = 0;
+ mfp->tot_len = sdulen;
+ mfp->reassembled = se_alloc(sdulen);
+ tvb_memcpy(tvb, mfp->reassembled, offset, length);
+ mfp->cur_off = length;
+ se_tree_insert32(config_data->start_fragments, pinfo->fd->num, mfp);
+ } else {
+ mfp = se_tree_lookup32(config_data->start_fragments, pinfo->fd->num);
+ }
+ if (mfp != NULL && mfp->last_frame) {
+ proto_item *item;
+ item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_reassembled_in, tvb, 0, 0, mfp->last_frame);
+ PROTO_ITEM_SET_GENERATED(item);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembled in #%u] ", mfp->last_frame);
+ }
+ } else {
+ length -= 4; /*Control, FCS*/
+ }
+ if (segment == 0x02 || segment == 0x03) {
+ mfp = se_tree_lookup32_le(config_data->start_fragments, pinfo->fd->num);
+ if (!pinfo->fd->flags.visited) {
+ if (mfp != NULL && !mfp->last_frame && (mfp->tot_len>=mfp->cur_off+length)) {
+ tvb_memcpy(tvb, mfp->reassembled+mfp->cur_off, offset, length);
+ mfp->cur_off += length;
+ if (segment == 0x02) {
+ mfp->last_frame = pinfo->fd->num;
+ }
+ }
+ }
+ if (mfp) {
+ proto_item *item;
+ item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_continuation_to, tvb, 0, 0, mfp->first_frame);
+ PROTO_ITEM_SET_GENERATED(item);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", mfp->first_frame);
+ }
+ }
+ if (segment == 0x02 && mfp != NULL && mfp->last_frame == pinfo->fd->num) {
+ next_tvb = tvb_new_child_real_data(tvb, (guint8 *)mfp->reassembled, mfp->tot_len, mfp->tot_len);
+ add_new_data_source(pinfo, next_tvb, "Reassembled L2CAP");
+ }
+ /*pass up to higher layer if we have a complete packet*/
+ if (segment == 0x00) {
+ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset) - 2, length);
+ }
+ if (next_tvb) {
+ if (psm) {
+ guint32 *service = se_tree_lookup32(psm_to_service_table, ((psm_data?psm_data->local_service:0)<<31) | psm);
+ proto_item *psm_item;
+
+ if (psm < BTL2CAP_DYNAMIC_PSM_START) {
+ psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 0, psm);
+ }
+ else {
+ psm_item = proto_tree_add_uint(btl2cap_tree, hf_btl2cap_psm_dynamic, tvb, offset, 0, psm);
+ if (service)
+ proto_item_append_text(psm_item," (%s)",
+ val_to_str_ext_const(*service, &vs_service_classes_ext, "Unknown service"));
+ }
+ PROTO_ITEM_SET_GENERATED(psm_item);
+
+ /* call next dissector */
+ if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
+ /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
+ if ((service == NULL) || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
+ /* unknown protocol. declare as data */
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_length(next_tvb), ENC_NA);
+ }
+ }
+ }
+ else {
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, next_tvb, 0, tvb_length(next_tvb), ENC_NA);
+ }
+ }
+ offset += (tvb_length_remaining(tvb, offset) - 2);
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ return offset;
}
static int
-dissect_s_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, proto_tree *btl2cap_tree, guint16 psm _U_, guint16 length _U_, int offset, config_data_t *config_data _U_)
+dissect_s_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, proto_tree *btl2cap_tree,
+ guint16 psm _U_, guint16 length _U_, int offset, config_data_t *config_data _U_)
{
- proto_item* ti_control;
- proto_tree* ti_control_subtree;
- guint16 control;
-
- control = tvb_get_letohs(tvb, offset);
- switch((control & 0x000C) >> 2)
- {
- case 0:
- col_append_str(pinfo->cinfo, COL_INFO, "[S] Receiver Ready");
- break;
- case 1:
- col_append_str(pinfo->cinfo, COL_INFO, "[S] Reject");
- break;
- default:
- col_append_str(pinfo->cinfo, COL_INFO, "[S] Unknown supervisory frame");
- break;
- }
- ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
- offset, 2, "Control: %s reqseq:%d r:%d",
- val_to_str((control & 0x000C) >> 2, control_supervisory_vals, "unknown"),
- (control & 0x3F00) >> 8,
- (control & 0x0080) >> 7);
- ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_supervisory, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- return offset;
+ proto_item *ti_control;
+ proto_tree *ti_control_subtree;
+ guint16 control;
+
+ control = tvb_get_letohs(tvb, offset);
+ switch ((control & 0x000C) >> 2) {
+ case 0:
+ col_append_str(pinfo->cinfo, COL_INFO, "[S] Receiver Ready");
+ break;
+ case 1:
+ col_append_str(pinfo->cinfo, COL_INFO, "[S] Reject");
+ break;
+ default:
+ col_append_str(pinfo->cinfo, COL_INFO, "[S] Unknown supervisory frame");
+ break;
+ }
+ ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
+ offset, 2, "Control: %s reqseq:%d r:%d",
+ val_to_str_const((control & 0x000C) >> 2, control_supervisory_vals, "unknown"),
+ (control & 0x3F00) >> 8,
+ (control & 0x0080) >> 7);
+ ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_supervisory, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_fcs, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ return offset;
}
/* Code to actually dissect the packets
@@ -1159,285 +1171,288 @@ dissect_s_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, proto_t
static void
dissect_btl2cap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- int offset=0;
- proto_item *ti=NULL;
- proto_tree *btl2cap_tree=NULL;
- guint16 length, cid;
- guint16 psm;
- guint16 control;
- tvbuff_t *next_tvb = NULL;
- psm_data_t *psm_data;
- bthci_acl_data_t *acl_data;
- btl2cap_data_t *l2cap_data;
- config_data_t *config_data;
- void* pd_save;
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2CAP");
- switch (pinfo->p2p_dir) {
-
- case P2P_DIR_SENT:
- col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
- break;
-
- case P2P_DIR_RECV:
- col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
- break;
-
- case P2P_DIR_UNKNOWN:
- col_clear(pinfo->cinfo, COL_INFO);
- break;
-
- default:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
- pinfo->p2p_dir);
- break;
- }
-
- if(tree){
- ti=proto_tree_add_item(tree, proto_btl2cap, tvb, offset, -1, ENC_NA);
- btl2cap_tree=proto_item_add_subtree(ti, ett_btl2cap);
- }
-
- length = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- cid = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- acl_data=(bthci_acl_data_t *)pinfo->private_data;
- l2cap_data=ep_alloc(sizeof(btl2cap_data_t));
- l2cap_data->chandle=acl_data->chandle;
- l2cap_data->cid=cid;
- pd_save = pinfo->private_data;
- pinfo->private_data=l2cap_data;
-
- if(cid==BTL2CAP_FIXED_CID_SIGNAL){ /* This is a command packet*/
- while(offset<(length+4)) {
- proto_tree *btl2cap_cmd_tree=NULL;
- proto_item *ti_command=NULL;
- guint8 cmd_code;
- guint16 cmd_length;
- const gchar *cmd_str;
-
- ti_command=proto_tree_add_none_format(btl2cap_tree,
- hf_btl2cap_command, tvb,
- offset, length,
- "Command: ");
- btl2cap_cmd_tree=proto_item_add_subtree(ti_command, ett_btl2cap_cmd);
-
- cmd_code=tvb_get_guint8(tvb, offset);
- proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_ident, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- cmd_length=tvb_get_letohs(tvb, offset);
- proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_item_set_len(ti_command, cmd_length+4);
- offset+=2;
-
- cmd_str = val_to_str(cmd_code, command_code_vals, "Unknown cmd");
- proto_item_append_text(ti_command,"%s", cmd_str);
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s", cmd_str);
-
- switch(cmd_code) {
- case 0x01: /* Command Reject */
- offset=dissect_comrej(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x02: /* Connection Request */
- offset=dissect_connrequest(tvb, offset, pinfo, btl2cap_cmd_tree, FALSE);
- break;
-
- case 0x03: /* Connection Response */
- offset=dissect_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x04: /* Configure Request */
- offset=dissect_configrequest(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length);
- break;
-
- case 0x05: /* Configure Response */
- offset=dissect_configresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length);
- break;
-
- case 0x06: /* Disconnect Request */
- offset=dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x07: /* Disconnect Response */
- offset=dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x08: /* Echo Request */
- offset+=tvb_length_remaining(tvb, offset);
- break;
-
- case 0x09: /* Echo Response */
- offset+=tvb_length_remaining(tvb, offset);
- break;
-
- case 0x0a: /* Information Request */
- offset=dissect_inforequest(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x0b: /* Information Response */
- offset=dissect_inforesponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x0c: /* Create Channel Request */
- offset=dissect_connrequest(tvb, offset, pinfo, btl2cap_cmd_tree, TRUE);
- break;
-
- case 0x0d: /* Create Channel Response */
- offset=dissect_chanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x0e: /* Move Channel Request */
- offset=dissect_movechanrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x0f: /* Move Channel Response */
- offset=dissect_movechanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x10: /* Move Channel Confirmation */
- offset=dissect_movechanconfirmation(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- case 0x11: /* Move Channel Confirmation Response */
- offset=dissect_movechanconfirmationresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
- break;
-
- default:
- proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_data, tvb, offset, -1, ENC_NA);
- offset+=tvb_length_remaining(tvb, offset);
- break;
- }
- }
- }
- else if (cid == BTL2CAP_FIXED_CID_CONNLESS) { /* Connectionless reception channel */
- col_append_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel");
-
- psm = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
-
- /* call next dissector */
- if(!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
- /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
- guint32 *service;
- service=se_tree_lookup32(psm_to_service_table, ((pinfo->p2p_dir==P2P_DIR_RECV)?0x80000000:0) | psm);
-
- if(!service || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
- /* unknown protocol. declare as data */
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
- }
- }
- }
- else if(cid < BTL2CAP_FIXED_CID_MAX) {
- if (cid == BTL2CAP_FIXED_CID_AMP_MAN) {
- control = tvb_get_letohs(tvb, offset);
- if(control & 0x1) {
- dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, 0 /* unused */, length, offset, NULL /* unused */);
- } else {
- proto_item* ti_control;
- proto_tree* ti_control_subtree;
-
- ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
- offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
- val_to_str((control & 0xC000) >> 14, control_sar_vals, "unknown"),
- (control & 0x3F00) >> 8,
- (control & 0x0080) >> 7,
- (control & 0x007E) >> 1);
- ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, tvb_length(tvb)-2, 2, ENC_LITTLE_ENDIAN);
-
- next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset)-2, length);
- }
- }
- else {
- next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
- }
- /* call next dissector */
- if(next_tvb && !dissector_try_uint(l2cap_cid_dissector_table, (guint32) cid,
- next_tvb, pinfo, tree)){
- /* unknown protocol. declare as data */
- proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
- }
- }
- else /* if(cid >= BTL2CAP_FIXED_CID_MAX) */ { /* Connection oriented channel */
- emem_tree_key_t key[3];
- guint32 kcid;
- guint32 frame_number;
-
- frame_number = pinfo->fd->num;
- kcid = cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
-
- key[0].length = 1;
- key[0].key = &kcid;
- key[1].length = 1;
- key[1].key = &frame_number;
- key[2].length = 0;
- key[2].key = NULL;
-
- psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
-
- if (psm_data && (psm_data->scid == (cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)) || (psm_data->dcid == (cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000))))) {
- psm=psm_data->psm;
-
- if(pinfo->p2p_dir==P2P_DIR_RECV)
- config_data = &(psm_data->in);
- else
- config_data = &(psm_data->out);
- if(config_data->mode == 0) {
- dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, psm_data->local_service, length, offset);
- } else {
- control = tvb_get_letohs(tvb, offset);
- if(control & 0x1) {
- dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, psm, length, offset, config_data);
- } else {
- dissect_i_frame(tvb, pinfo, tree, btl2cap_tree, psm_data, length, offset, config_data);
- }
- }
- } else {
- psm=0;
- dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, FALSE, length, offset);
- }
- }
- pinfo->private_data = pd_save;
+ int offset = 0;
+ proto_tree *btl2cap_tree = NULL;
+ guint16 length, cid;
+ guint16 psm;
+ guint16 control;
+ tvbuff_t *next_tvb = NULL;
+ psm_data_t *psm_data;
+ bthci_acl_data_t *acl_data;
+ btl2cap_data_t *l2cap_data;
+ config_data_t *config_data;
+ void* pd_save;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2CAP");
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
+ break;
+
+ case P2P_DIR_RECV:
+ col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
+ break;
+
+ case P2P_DIR_UNKNOWN:
+ col_clear(pinfo->cinfo, COL_INFO);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
+ pinfo->p2p_dir);
+ break;
+ }
+
+ if (tree) {
+ proto_item *ti;
+ ti = proto_tree_add_item(tree, proto_btl2cap, tvb, offset, -1, ENC_NA);
+ btl2cap_tree = proto_item_add_subtree(ti, ett_btl2cap);
+ }
+
+ length = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ cid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_cid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ acl_data = (bthci_acl_data_t *)pinfo->private_data;
+ l2cap_data = ep_alloc(sizeof(btl2cap_data_t));
+ l2cap_data->chandle = acl_data->chandle;
+ l2cap_data->cid = cid;
+ pd_save = pinfo->private_data;
+ pinfo->private_data = l2cap_data;
+
+ if (cid == BTL2CAP_FIXED_CID_SIGNAL) { /* This is a command packet*/
+ while (offset < (length+4)) {
+ proto_item *ti_command;
+ proto_tree *btl2cap_cmd_tree;
+ guint8 cmd_code;
+ guint16 cmd_length;
+ const gchar *cmd_str;
+
+ ti_command = proto_tree_add_none_format(btl2cap_tree,
+ hf_btl2cap_command, tvb,
+ offset, length,
+ "Command: ");
+ btl2cap_cmd_tree = proto_item_add_subtree(ti_command, ett_btl2cap_cmd);
+
+ cmd_code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_ident, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ cmd_length = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_item_set_len(ti_command, cmd_length+4);
+ offset += 2;
+
+ cmd_str = val_to_str_const(cmd_code, command_code_vals, "Unknown cmd");
+ proto_item_append_text(ti_command,"%s", cmd_str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", cmd_str);
+
+ switch (cmd_code) {
+ case 0x01: /* Command Reject */
+ offset = dissect_comrej(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x02: /* Connection Request */
+ offset = dissect_connrequest(tvb, offset, pinfo, btl2cap_cmd_tree, FALSE);
+ break;
+
+ case 0x03: /* Connection Response */
+ offset = dissect_connresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x04: /* Configure Request */
+ offset = dissect_configrequest(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length);
+ break;
+
+ case 0x05: /* Configure Response */
+ offset = dissect_configresponse(tvb, offset, pinfo, btl2cap_cmd_tree, cmd_length);
+ break;
+
+ case 0x06: /* Disconnect Request */
+ offset = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x07: /* Disconnect Response */
+ offset = dissect_disconnrequestresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x08: /* Echo Request */
+ offset += tvb_reported_length_remaining(tvb, offset);
+ break;
+
+ case 0x09: /* Echo Response */
+ offset += tvb_reported_length_remaining(tvb, offset);
+ break;
+
+ case 0x0a: /* Information Request */
+ offset = dissect_inforequest(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x0b: /* Information Response */
+ offset = dissect_inforesponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x0c: /* Create Channel Request */
+ offset = dissect_connrequest(tvb, offset, pinfo, btl2cap_cmd_tree, TRUE);
+ break;
+
+ case 0x0d: /* Create Channel Response */
+ offset = dissect_chanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x0e: /* Move Channel Request */
+ offset = dissect_movechanrequest(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x0f: /* Move Channel Response */
+ offset = dissect_movechanresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x10: /* Move Channel Confirmation */
+ offset = dissect_movechanconfirmation(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ case 0x11: /* Move Channel Confirmation Response */
+ offset = dissect_movechanconfirmationresponse(tvb, offset, pinfo, btl2cap_cmd_tree);
+ break;
+
+ default:
+ proto_tree_add_item(btl2cap_cmd_tree, hf_btl2cap_cmd_data, tvb, offset, -1, ENC_NA);
+ offset += tvb_reported_length_remaining(tvb, offset);
+ break;
+ }
+ }
+ }
+ else if (cid == BTL2CAP_FIXED_CID_CONNLESS) { /* Connectionless reception channel */
+ col_append_str(pinfo->cinfo, COL_INFO, "Connectionless reception channel");
+
+ psm = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_psm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
+
+ /* call next dissector */
+ if (!dissector_try_uint(l2cap_psm_dissector_table, (guint32) psm, next_tvb, pinfo, tree)) {
+ /* not a known fixed PSM, try to find a registered service to a dynamic PSM */
+ guint32 *service;
+ service = se_tree_lookup32(psm_to_service_table, ((pinfo->p2p_dir == P2P_DIR_RECV)?0x80000000:0) | psm);
+
+ if ((service == NULL) || !dissector_try_uint(l2cap_service_dissector_table, *service, next_tvb, pinfo, tree)) {
+ /* unknown protocol. declare as data */
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
+ }
+ }
+ }
+ else if (cid < BTL2CAP_FIXED_CID_MAX) {
+ if (cid == BTL2CAP_FIXED_CID_AMP_MAN) {
+ control = tvb_get_letohs(tvb, offset);
+ if (control & 0x1) {
+ dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, 0 /* unused */, length, offset, NULL /* unused */);
+ } else {
+ proto_item* ti_control;
+ proto_tree* ti_control_subtree;
+
+ ti_control = proto_tree_add_none_format(btl2cap_tree, hf_btl2cap_control, tvb,
+ offset, 2, "Control: %s reqseq:%d r:%d txseq:%d",
+ val_to_str_const((control & 0xC000) >> 14, control_sar_vals, "unknown"),
+ (control & 0x3F00) >> 8,
+ (control & 0x0080) >> 7,
+ (control & 0x007E) >> 1);
+ ti_control_subtree = proto_item_add_subtree(ti_control, ett_btl2cap_control);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_sar, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_reqseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_retransmissiondisable, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_txseq, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(ti_control_subtree, hf_btl2cap_control_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_fcs, tvb, tvb_length(tvb)-2, 2, ENC_LITTLE_ENDIAN);
+
+ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset)-2, length);
+ }
+ }
+ else {
+ next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), length);
+ }
+ /* call next dissector */
+ if (next_tvb && !dissector_try_uint(l2cap_cid_dissector_table, (guint32) cid,
+ next_tvb, pinfo, tree)) {
+ /* unknown protocol. declare as data */
+ proto_tree_add_item(btl2cap_tree, hf_btl2cap_payload, tvb, offset, length, ENC_NA);
+ }
+ }
+ else /* if (cid >= BTL2CAP_FIXED_CID_MAX) */ { /* Connection oriented channel */
+ emem_tree_key_t key[3];
+ guint32 kcid;
+ guint32 frame_number;
+
+ frame_number = pinfo->fd->num;
+ kcid = cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000);
+
+ key[0].length = 1;
+ key[0].key = &kcid;
+ key[1].length = 1;
+ key[1].key = &frame_number;
+ key[2].length = 0;
+ key[2].key = NULL;
+
+ psm_data = se_tree_lookup32_array_le(cid_to_psm_table, key);
+
+ if (psm_data &&
+ ((psm_data->scid == (cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000)))
+ || (psm_data->dcid == (cid | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x0000 : 0x8000))))
+ ) {
+ psm = psm_data->psm;
+
+ if (pinfo->p2p_dir == P2P_DIR_RECV)
+ config_data = &(psm_data->in);
+ else
+ config_data = &(psm_data->out);
+ if (config_data->mode == 0) {
+ dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, psm_data->local_service, length, offset);
+ } else {
+ control = tvb_get_letohs(tvb, offset);
+ if (control & 0x1) {
+ dissect_s_frame(tvb, pinfo, tree, btl2cap_tree, psm, length, offset, config_data);
+ } else {
+ dissect_i_frame(tvb, pinfo, tree, btl2cap_tree, psm_data, length, offset, config_data);
+ }
+ }
+ } else {
+ psm = 0;
+ dissect_b_frame(tvb, pinfo, tree, btl2cap_tree, psm, FALSE, length, offset);
+ }
+ }
+ pinfo->private_data = pd_save;
}
static int
btl2cap_sdp_tap_packet(void *arg _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *arg2)
{
- btsdp_data_t *sdp_data = (btsdp_data_t *) arg2;
+ btsdp_data_t *sdp_data = (btsdp_data_t *) arg2;
- if( sdp_data->protocol == BTSDP_L2CAP_PROTOCOL_UUID ) {
- guint32 token, *psm_service;
+ if (sdp_data->protocol == BTSDP_L2CAP_PROTOCOL_UUID) {
+ guint32 token, *psm_service;
- token = sdp_data->channel | ((sdp_data->flags & BTSDP_LOCAL_SERVICE_FLAG_MASK)<<31);
+ token = sdp_data->channel | ((sdp_data->flags & BTSDP_LOCAL_SERVICE_FLAG_MASK)<<31);
- psm_service=se_tree_lookup32(psm_to_service_table, token);
- if(!psm_service){
- psm_service=se_alloc0(sizeof(guint32));
- se_tree_insert32(psm_to_service_table, token, psm_service);
- }
- *psm_service = sdp_data->service;
- }
- return 0;
+ psm_service = se_tree_lookup32(psm_to_service_table, token);
+ if (!psm_service) {
+ psm_service = se_alloc0(sizeof(guint32));
+ se_tree_insert32(psm_to_service_table, token, psm_service);
+ }
+ *psm_service = sdp_data->service;
+ }
+ return 0;
}
@@ -1446,441 +1461,441 @@ void
proto_register_btl2cap(void)
{
- /* Setup list of header fields See Section 1.6.1 for details*/
- static hf_register_info hf[] = {
- { &hf_btl2cap_length,
- { "Length", "btl2cap.length",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "L2CAP Payload Length", HFILL }
- },
- { &hf_btl2cap_cid,
- { "CID", "btl2cap.cid",
- FT_UINT16, BASE_HEX, NULL, 0x0,
- "L2CAP Channel Identifier", HFILL }
- },
- { &hf_btl2cap_payload,
- { "Payload", "btl2cap.payload",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "L2CAP Payload", HFILL }
- },
- { &hf_btl2cap_command,
- { "Command", "btl2cap.command",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "L2CAP Command", HFILL }
- },
- { &hf_btl2cap_cmd_code,
- { "Command Code", "btl2cap.cmd_code",
- FT_UINT8, BASE_HEX, VALS(command_code_vals), 0x0,
- "L2CAP Command Code", HFILL }
- },
- { &hf_btl2cap_cmd_ident,
- { "Command Identifier", "btl2cap.cmd_ident",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "L2CAP Command Identifier", HFILL }
- },
- { &hf_btl2cap_cmd_length,
- { "Command Length", "btl2cap.cmd_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "L2CAP Command Length", HFILL }
- },
- { &hf_btl2cap_cmd_data,
- { "Command Data", "btl2cap.cmd_data",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "L2CAP Command Data", HFILL }
- },
- { &hf_btl2cap_psm,
- { "PSM", "btl2cap.psm",
- FT_UINT16, BASE_HEX, VALS(psm_vals), 0x0,
- "Protocol/Service Multiplexer", HFILL }
- },
- { &hf_btl2cap_psm_dynamic,
- { "Dynamic PSM", "btl2cap.psm",
- FT_UINT16, BASE_HEX, NULL, 0x0,
- "Dynamic Protocol/Service Multiplexer", HFILL }
- },
- { &hf_btl2cap_scid,
- { "Source CID", "btl2cap.scid",
- FT_UINT16, BASE_HEX, NULL, 0x0,
- "Source Channel Identifier", HFILL }
- },
- { &hf_btl2cap_dcid,
- { "Destination CID", "btl2cap.dcid",
- FT_UINT16, BASE_HEX, NULL, 0x0,
- "Destination Channel Identifier", HFILL }
- },
- { &hf_btl2cap_icid,
- { "Initiator CID", "btl2cap.icid",
- FT_UINT16, BASE_HEX, NULL, 0x0,
- "Initiator Channel Identifier", HFILL }
- },
- { &hf_btl2cap_controller,
- { "Controller ID", "btl2cap.ctrl_id",
- FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_dcontroller,
- { "Controller ID", "btl2cap.dctrl_id",
- FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
- "Destination Controller ID", HFILL }
- },
- { &hf_btl2cap_result,
- { "Result", "btl2cap.result",
- FT_UINT16, BASE_HEX, VALS(result_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_move_result,
- { "Move Result", "btl2cap.move_result",
- FT_UINT16, BASE_HEX, VALS(move_result_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_move_confirmation_result,
- { "Move Result", "btl2cap.move_result",
- FT_UINT16, BASE_HEX, VALS(move_result_confirmation_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_status,
- { "Status", "btl2cap.status",
- FT_UINT16, BASE_HEX, VALS(status_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_rej_reason,
- { "Reason", "btl2cap.rej_reason",
- FT_UINT16, BASE_HEX, VALS(reason_vals), 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_sig_mtu,
- { "Maximum Signalling MTU", "btl2cap.sig_mtu",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_mtu,
- { "Remote Entity MTU", "btl2cap.info_mtu",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Remote entity acceptable connectionless MTU", HFILL }
- },
- { &hf_btl2cap_info_flowcontrol,
- { "Flow Control Mode", "btl2cap.info_flowcontrol",
- FT_UINT32, BASE_DEC, NULL, 0x01,
- "Flow Control mode support", HFILL }
- },
- { &hf_btl2cap_info_retransmission,
- { "Retransmission Mode", "btl2cap.info_retransmission",
- FT_UINT32, BASE_DEC, NULL, 0x02,
- "Retransmission mode support", HFILL }
- },
- { &hf_btl2cap_info_bidirqos,
- { "Bi-Directional QOS", "btl2cap.info_bidirqos",
- FT_UINT32, BASE_DEC, NULL, 0x04,
- "Bi-Directional QOS support", HFILL }
- },
- { &hf_btl2cap_info_enh_retransmission,
- { "Enhancded Retransmission Mode", "btl2cap.info_enh_retransmission",
- FT_UINT32, BASE_DEC, NULL, 0x08,
- "Enhancded Retransmission mode support", HFILL }
- },
- { &hf_btl2cap_info_streaming,
- { "Streaming Mode", "btl2cap.info_streaming",
- FT_UINT32, BASE_DEC, NULL, 0x10,
- "Streaming mode support", HFILL }
- },
- { &hf_btl2cap_info_fcs,
- { "FCS", "btl2cap.info_fcs",
- FT_UINT32, BASE_DEC, NULL, 0x20,
- "FCS support", HFILL }
- },
- { &hf_btl2cap_info_flow_spec,
- { "Extended Flow Specification for BR/EDR", "btl2cap.info_flow_spec",
- FT_UINT32, BASE_DEC, NULL, 0x40,
- "Extended Flow Specification for BR/EDR support", HFILL }
- },
- { &hf_btl2cap_info_fixedchan,
- { "Fixed Channels", "btl2cap.info_fixedchan",
- FT_UINT32, BASE_DEC, NULL, 0x80,
- "Fixed Channels support", HFILL }
- },
- { &hf_btl2cap_info_window,
- { "Extended Window Size", "btl2cap.info_window",
- FT_UINT32, BASE_DEC, NULL, 0x01,
- "Extended Window Size support", HFILL }
- },
- { &hf_btl2cap_info_unicast,
- { "Unicast Connectionless Data Reception", "btl2cap.info_unicast",
- FT_UINT32, BASE_DEC, NULL, 0x02,
- "Unicast Connectionless Data Reception support", HFILL }
- },
- { &hf_btl2cap_info_fixedchans,
- { "Fixed Channels", "btl2cap.info_fixedchans",
- FT_NONE, BASE_NONE, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_fixedchans_null,
- { "Null identifier", "btl2cap.info_fixedchans_null",
- FT_UINT32, BASE_DEC, NULL, 0x1,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_fixedchans_signal,
- { "L2CAP signaling channel", "btl2cap.info_fixedchans_signal",
- FT_UINT32, BASE_DEC, NULL, 0x2,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_fixedchans_connless,
- { "Connectionless reception", "btl2cap.info_fixedchans_connless",
- FT_UINT32, BASE_DEC, NULL, 0x4,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_fixedchans_amp_man,
- { "AMP Manager protocol", "btl2cap.info_fixedchans_amp_man",
- FT_UINT32, BASE_DEC, NULL, 0x8,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_fixedchans_amp_test,
- { "AMP Test Manager", "btl2cap.info_fixedchans_amp_test",
- FT_UINT32, BASE_DEC, NULL, 0x80000000,
- NULL, HFILL }
- },
- { &hf_btl2cap_info_type,
- { "Information Type", "btl2cap.info_type",
- FT_UINT16, BASE_HEX, VALS(info_type_vals), 0x0,
- "Type of implementation-specific information", HFILL }
- },
- { &hf_btl2cap_info_result,
- { "Result", "btl2cap.info_result",
- FT_UINT16, BASE_HEX, VALS(info_result_vals), 0x0,
- "Information about the success of the request", HFILL }
- },
- { &hf_btl2cap_info_extfeatures,
- { "Extended Features", "btl2cap.info_extfeatures",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Extended Features Mask", HFILL }
- },
- { &hf_btl2cap_continuation_flag,
- { "Continuation Flag", "btl2cap.continuation",
- FT_BOOLEAN, 16, NULL, 0x0001,
- NULL, HFILL }
- },
- { &hf_btl2cap_configuration_result,
- { "Result", "btl2cap.conf_result",
- FT_UINT16, BASE_HEX, VALS(configuration_result_vals), 0x0,
- "Configuration Result", HFILL }
- },
- { &hf_btl2cap_option_type,
- { "Type", "btl2cap.option_type",
- FT_UINT8, BASE_HEX, VALS(option_type_vals), 0x0,
- "Type of option", HFILL }
- },
- { &hf_btl2cap_option_length,
- { "Length", "btl2cap.option_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Number of octets in option payload", HFILL }
- },
- { &hf_btl2cap_option_mtu,
- { "MTU", "btl2cap.option_mtu",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Maximum Transmission Unit", HFILL }
- },
- { &hf_btl2cap_option_flushTO,
- { "Flush Timeout (ms)", "btl2cap.option_flushto",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Flush Timeout in milliseconds", HFILL }
- },
- { &hf_btl2cap_option_flush_to_us,
- { "Flush Timeout (us)", "btl2cap.option_flushto",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Flush Timeout (microseconds)", HFILL }
- },
- { &hf_btl2cap_option_sdu_size,
- { "Maximum SDU Size", "btl2cap.option_sdu_size",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_option_sdu_arrival_time,
- { "SDU Inter-arrival Time (us)", "btl2cap.option_sdu_arrival_time",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SDU Inter-arrival Time (microseconds)", HFILL }
- },
- { &hf_btl2cap_option_identifier,
- { "Identifier", "btl2cap.option_ident",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "Flow Specification Identifier", HFILL }
- },
- { &hf_btl2cap_option_access_latency,
- { "Access Latency (us)", "btl2cap.option_access_latency",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Access Latency (microseconds)", HFILL }
- },
- { &hf_btl2cap_option_flags,
- { "Flags", "btl2cap.option_flags",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "Flags - must be set to 0 (Reserved for future use)", HFILL }
- },
- { &hf_btl2cap_option_service_type,
- { "Service Type", "btl2cap.option_servicetype",
- FT_UINT8, BASE_HEX, VALS(option_servicetype_vals), 0x0,
- "Level of service required", HFILL }
- },
- { &hf_btl2cap_option_tokenrate,
- { "Token Rate (bytes/s)", "btl2cap.option_tokenrate",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Rate at which traffic credits are granted (bytes/s)", HFILL }
- },
- { &hf_btl2cap_option_tokenbucketsize,
- { "Token Bucket Size (bytes)", "btl2cap.option_tokenbsize",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Size of the token bucket (bytes)", HFILL }
- },
- { &hf_btl2cap_option_peakbandwidth,
- { "Peak Bandwidth (bytes/s)", "btl2cap.option_peakbandwidth",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Limit how fast packets may be sent (bytes/s)", HFILL }
- },
- { &hf_btl2cap_option_latency,
- { "Latency (microseconds)", "btl2cap.option_latency",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Maximal acceptable delay (microseconds)", HFILL }
- },
- { &hf_btl2cap_option_delayvariation,
- { "Delay Variation (microseconds)", "btl2cap.option_delayvar",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "Difference between maximum and minimum delay (microseconds)", HFILL }
- },
- { &hf_btl2cap_option_retransmissionmode,
- { "Mode", "btl2cap.retransmissionmode",
- FT_UINT8, BASE_HEX, VALS(option_retransmissionmode_vals), 0x0,
- "Retransmission/Flow Control mode", HFILL }
- },
- { &hf_btl2cap_option_txwindow,
- { "TxWindow", "btl2cap.txwindow",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Retransmission window size", HFILL }
- },
- { &hf_btl2cap_option_maxtransmit,
- { "MaxTransmit", "btl2cap.maxtransmit",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Maximum I-frame retransmissions", HFILL }
- },
- { &hf_btl2cap_option_retransmittimeout,
- { "Retransmit timeout (ms)", "btl2cap.retransmittimeout",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Retransmission timeout (milliseconds)", HFILL }
- },
- { &hf_btl2cap_option_monitortimeout,
- { "Monitor Timeout (ms)", "btl2cap.monitortimeout",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "S-frame transmission interval (milliseconds)", HFILL }
- },
- { &hf_btl2cap_option_mps,
- { "MPS", "btl2cap.mps",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Maximum PDU Payload Size", HFILL }
- },
- { &hf_btl2cap_option_fcs,
- { "FCS", "btl2cap.option_fcs",
- FT_UINT16, BASE_HEX, VALS(option_fcs_vals), 0x0,
- "Frame Check Sequence", HFILL }
- },
- { &hf_btl2cap_option_window,
- { "Extended Window Size", "btl2cap.option_window",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_option,
- { "Configuration Parameter Option", "btl2cap.conf_param_option",
- FT_NONE, BASE_NONE, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_control_sar,
- { "Segmentation and reassembly", "btl2cap.control_sar",
- FT_UINT16, BASE_HEX, VALS(control_sar_vals), 0xC000,
- NULL, HFILL }
- },
- { &hf_btl2cap_control_reqseq,
- { "ReqSeq", "btl2cap.control_reqseq",
- FT_UINT16, BASE_DEC, NULL, 0x3F00,
- "Request Sequence Number", HFILL }
- },
- { &hf_btl2cap_control_txseq,
- { "TxSeq", "btl2cap.control_txseq",
- FT_UINT16, BASE_DEC, NULL, 0x007E,
- "Transmitted Sequence Number", HFILL }
- },
- { &hf_btl2cap_control_retransmissiondisable,
- { "R", "btl2cap.control_retransmissiondisable",
- FT_UINT16, BASE_HEX, NULL, 0x0080,
- "Retransmission Disable", HFILL }
- },
- { &hf_btl2cap_control_supervisory,
- { "S", "btl2cap.control_supervisory",
- FT_UINT16, BASE_HEX, VALS(control_supervisory_vals), 0x000C,
- "Supervisory Function", HFILL }
- },
- { &hf_btl2cap_control_type,
- { "Frame Type", "btl2cap.control_type",
- FT_UINT16, BASE_HEX, VALS(control_type_vals), 0x0001,
- NULL, HFILL }
- },
- { &hf_btl2cap_control,
- { "Control field", "btl2cap.control",
- FT_NONE, BASE_NONE, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btl2cap_fcs,
- { "FCS", "btl2cap.fcs",
- FT_UINT16, BASE_HEX, NULL, 0,
- "Frame Check Sequence", HFILL }
- },
- { &hf_btl2cap_sdulength,
- { "SDU Length", "btl2cap.sdulength",
- FT_UINT16, BASE_DEC, NULL, 0,
- NULL, HFILL }
- },
- { &hf_btl2cap_reassembled_in,
- { "This SDU is reassembled in frame", "btl2cap.reassembled_in",
- FT_FRAMENUM, BASE_NONE, NULL, 0,
- "This SDU is reassembled in frame #", HFILL }
- },
- { &hf_btl2cap_continuation_to,
- { "This is a continuation to the SDU in frame", "btl2cap.continuation_to",
- FT_FRAMENUM, BASE_NONE, NULL, 0,
- "This is a continuation to the SDU in frame #", HFILL }
- }
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btl2cap,
- &ett_btl2cap_cmd,
- &ett_btl2cap_option,
- &ett_btl2cap_extfeatures,
- &ett_btl2cap_fixedchans,
- &ett_btl2cap_control
- };
-
- /* Register the protocol name and description */
- proto_btl2cap = proto_register_protocol("Bluetooth L2CAP Protocol", "L2CAP", "btl2cap");
-
- register_dissector("btl2cap", dissect_btl2cap, proto_btl2cap);
-
- /* subdissector code */
- l2cap_psm_dissector_table = register_dissector_table("btl2cap.psm", "L2CAP PSM", FT_UINT16, BASE_HEX);
- l2cap_service_dissector_table = register_dissector_table("btl2cap.service", "L2CAP Service", FT_UINT16, BASE_HEX);
- l2cap_cid_dissector_table = register_dissector_table("btl2cap.cid", "L2CAP CID", FT_UINT16, BASE_HEX);
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_btl2cap, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- cid_to_psm_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btl2cap scid to psm");
- psm_to_service_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btl2cap psm to service uuid");
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_btl2cap_length,
+ { "Length", "btl2cap.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "L2CAP Payload Length", HFILL }
+ },
+ { &hf_btl2cap_cid,
+ { "CID", "btl2cap.cid",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "L2CAP Channel Identifier", HFILL }
+ },
+ { &hf_btl2cap_payload,
+ { "Payload", "btl2cap.payload",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "L2CAP Payload", HFILL }
+ },
+ { &hf_btl2cap_command,
+ { "Command", "btl2cap.command",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "L2CAP Command", HFILL }
+ },
+ { &hf_btl2cap_cmd_code,
+ { "Command Code", "btl2cap.cmd_code",
+ FT_UINT8, BASE_HEX, VALS(command_code_vals), 0x0,
+ "L2CAP Command Code", HFILL }
+ },
+ { &hf_btl2cap_cmd_ident,
+ { "Command Identifier", "btl2cap.cmd_ident",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "L2CAP Command Identifier", HFILL }
+ },
+ { &hf_btl2cap_cmd_length,
+ { "Command Length", "btl2cap.cmd_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "L2CAP Command Length", HFILL }
+ },
+ { &hf_btl2cap_cmd_data,
+ { "Command Data", "btl2cap.cmd_data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "L2CAP Command Data", HFILL }
+ },
+ { &hf_btl2cap_psm,
+ { "PSM", "btl2cap.psm",
+ FT_UINT16, BASE_HEX, VALS(psm_vals), 0x0,
+ "Protocol/Service Multiplexer", HFILL }
+ },
+ { &hf_btl2cap_psm_dynamic,
+ { "Dynamic PSM", "btl2cap.psm",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Dynamic Protocol/Service Multiplexer", HFILL }
+ },
+ { &hf_btl2cap_scid,
+ { "Source CID", "btl2cap.scid",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Source Channel Identifier", HFILL }
+ },
+ { &hf_btl2cap_dcid,
+ { "Destination CID", "btl2cap.dcid",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Destination Channel Identifier", HFILL }
+ },
+ { &hf_btl2cap_icid,
+ { "Initiator CID", "btl2cap.icid",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Initiator Channel Identifier", HFILL }
+ },
+ { &hf_btl2cap_controller,
+ { "Controller ID", "btl2cap.ctrl_id",
+ FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_dcontroller,
+ { "Controller ID", "btl2cap.dctrl_id",
+ FT_UINT8, BASE_DEC, VALS(ctrl_id_code_vals), 0x0,
+ "Destination Controller ID", HFILL }
+ },
+ { &hf_btl2cap_result,
+ { "Result", "btl2cap.result",
+ FT_UINT16, BASE_HEX, VALS(result_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_move_result,
+ { "Move Result", "btl2cap.move_result",
+ FT_UINT16, BASE_HEX, VALS(move_result_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_move_confirmation_result,
+ { "Move Result", "btl2cap.move_result",
+ FT_UINT16, BASE_HEX, VALS(move_result_confirmation_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_status,
+ { "Status", "btl2cap.status",
+ FT_UINT16, BASE_HEX, VALS(status_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_rej_reason,
+ { "Reason", "btl2cap.rej_reason",
+ FT_UINT16, BASE_HEX, VALS(reason_vals), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_sig_mtu,
+ { "Maximum Signalling MTU", "btl2cap.sig_mtu",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_mtu,
+ { "Remote Entity MTU", "btl2cap.info_mtu",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Remote entity acceptable connectionless MTU", HFILL }
+ },
+ { &hf_btl2cap_info_flowcontrol,
+ { "Flow Control Mode", "btl2cap.info_flowcontrol",
+ FT_UINT32, BASE_DEC, NULL, 0x01,
+ "Flow Control mode support", HFILL }
+ },
+ { &hf_btl2cap_info_retransmission,
+ { "Retransmission Mode", "btl2cap.info_retransmission",
+ FT_UINT32, BASE_DEC, NULL, 0x02,
+ "Retransmission mode support", HFILL }
+ },
+ { &hf_btl2cap_info_bidirqos,
+ { "Bi-Directional QOS", "btl2cap.info_bidirqos",
+ FT_UINT32, BASE_DEC, NULL, 0x04,
+ "Bi-Directional QOS support", HFILL }
+ },
+ { &hf_btl2cap_info_enh_retransmission,
+ { "Enhancded Retransmission Mode", "btl2cap.info_enh_retransmission",
+ FT_UINT32, BASE_DEC, NULL, 0x08,
+ "Enhancded Retransmission mode support", HFILL }
+ },
+ { &hf_btl2cap_info_streaming,
+ { "Streaming Mode", "btl2cap.info_streaming",
+ FT_UINT32, BASE_DEC, NULL, 0x10,
+ "Streaming mode support", HFILL }
+ },
+ { &hf_btl2cap_info_fcs,
+ { "FCS", "btl2cap.info_fcs",
+ FT_UINT32, BASE_DEC, NULL, 0x20,
+ "FCS support", HFILL }
+ },
+ { &hf_btl2cap_info_flow_spec,
+ { "Extended Flow Specification for BR/EDR", "btl2cap.info_flow_spec",
+ FT_UINT32, BASE_DEC, NULL, 0x40,
+ "Extended Flow Specification for BR/EDR support", HFILL }
+ },
+ { &hf_btl2cap_info_fixedchan,
+ { "Fixed Channels", "btl2cap.info_fixedchan",
+ FT_UINT32, BASE_DEC, NULL, 0x80,
+ "Fixed Channels support", HFILL }
+ },
+ { &hf_btl2cap_info_window,
+ { "Extended Window Size", "btl2cap.info_window",
+ FT_UINT32, BASE_DEC, NULL, 0x01,
+ "Extended Window Size support", HFILL }
+ },
+ { &hf_btl2cap_info_unicast,
+ { "Unicast Connectionless Data Reception", "btl2cap.info_unicast",
+ FT_UINT32, BASE_DEC, NULL, 0x02,
+ "Unicast Connectionless Data Reception support", HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans,
+ { "Fixed Channels", "btl2cap.info_fixedchans",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans_null,
+ { "Null identifier", "btl2cap.info_fixedchans_null",
+ FT_UINT32, BASE_DEC, NULL, 0x1,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans_signal,
+ { "L2CAP signaling channel", "btl2cap.info_fixedchans_signal",
+ FT_UINT32, BASE_DEC, NULL, 0x2,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans_connless,
+ { "Connectionless reception", "btl2cap.info_fixedchans_connless",
+ FT_UINT32, BASE_DEC, NULL, 0x4,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans_amp_man,
+ { "AMP Manager protocol", "btl2cap.info_fixedchans_amp_man",
+ FT_UINT32, BASE_DEC, NULL, 0x8,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_fixedchans_amp_test,
+ { "AMP Test Manager", "btl2cap.info_fixedchans_amp_test",
+ FT_UINT32, BASE_DEC, NULL, 0x80000000,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_info_type,
+ { "Information Type", "btl2cap.info_type",
+ FT_UINT16, BASE_HEX, VALS(info_type_vals), 0x0,
+ "Type of implementation-specific information", HFILL }
+ },
+ { &hf_btl2cap_info_result,
+ { "Result", "btl2cap.info_result",
+ FT_UINT16, BASE_HEX, VALS(info_result_vals), 0x0,
+ "Information about the success of the request", HFILL }
+ },
+ { &hf_btl2cap_info_extfeatures,
+ { "Extended Features", "btl2cap.info_extfeatures",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Extended Features Mask", HFILL }
+ },
+ { &hf_btl2cap_continuation_flag,
+ { "Continuation Flag", "btl2cap.continuation",
+ FT_BOOLEAN, 16, NULL, 0x0001,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_configuration_result,
+ { "Result", "btl2cap.conf_result",
+ FT_UINT16, BASE_HEX, VALS(configuration_result_vals), 0x0,
+ "Configuration Result", HFILL }
+ },
+ { &hf_btl2cap_option_type,
+ { "Type", "btl2cap.option_type",
+ FT_UINT8, BASE_HEX, VALS(option_type_vals), 0x0,
+ "Type of option", HFILL }
+ },
+ { &hf_btl2cap_option_length,
+ { "Length", "btl2cap.option_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of octets in option payload", HFILL }
+ },
+ { &hf_btl2cap_option_mtu,
+ { "MTU", "btl2cap.option_mtu",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum Transmission Unit", HFILL }
+ },
+ { &hf_btl2cap_option_flushTO,
+ { "Flush Timeout (ms)", "btl2cap.option_flushto",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flush Timeout in milliseconds", HFILL }
+ },
+ { &hf_btl2cap_option_flush_to_us,
+ { "Flush Timeout (us)", "btl2cap.option_flushto",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Flush Timeout (microseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_sdu_size,
+ { "Maximum SDU Size", "btl2cap.option_sdu_size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_option_sdu_arrival_time,
+ { "SDU Inter-arrival Time (us)", "btl2cap.option_sdu_arrival_time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SDU Inter-arrival Time (microseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_identifier,
+ { "Identifier", "btl2cap.option_ident",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Flow Specification Identifier", HFILL }
+ },
+ { &hf_btl2cap_option_access_latency,
+ { "Access Latency (us)", "btl2cap.option_access_latency",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Access Latency (microseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_flags,
+ { "Flags", "btl2cap.option_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Flags - must be set to 0 (Reserved for future use)", HFILL }
+ },
+ { &hf_btl2cap_option_service_type,
+ { "Service Type", "btl2cap.option_servicetype",
+ FT_UINT8, BASE_HEX, VALS(option_servicetype_vals), 0x0,
+ "Level of service required", HFILL }
+ },
+ { &hf_btl2cap_option_tokenrate,
+ { "Token Rate (bytes/s)", "btl2cap.option_tokenrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Rate at which traffic credits are granted (bytes/s)", HFILL }
+ },
+ { &hf_btl2cap_option_tokenbucketsize,
+ { "Token Bucket Size (bytes)", "btl2cap.option_tokenbsize",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Size of the token bucket (bytes)", HFILL }
+ },
+ { &hf_btl2cap_option_peakbandwidth,
+ { "Peak Bandwidth (bytes/s)", "btl2cap.option_peakbandwidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Limit how fast packets may be sent (bytes/s)", HFILL }
+ },
+ { &hf_btl2cap_option_latency,
+ { "Latency (microseconds)", "btl2cap.option_latency",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Maximal acceptable delay (microseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_delayvariation,
+ { "Delay Variation (microseconds)", "btl2cap.option_delayvar",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Difference between maximum and minimum delay (microseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_retransmissionmode,
+ { "Mode", "btl2cap.retransmissionmode",
+ FT_UINT8, BASE_HEX, VALS(option_retransmissionmode_vals), 0x0,
+ "Retransmission/Flow Control mode", HFILL }
+ },
+ { &hf_btl2cap_option_txwindow,
+ { "TxWindow", "btl2cap.txwindow",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Retransmission window size", HFILL }
+ },
+ { &hf_btl2cap_option_maxtransmit,
+ { "MaxTransmit", "btl2cap.maxtransmit",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Maximum I-frame retransmissions", HFILL }
+ },
+ { &hf_btl2cap_option_retransmittimeout,
+ { "Retransmit timeout (ms)", "btl2cap.retransmittimeout",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Retransmission timeout (milliseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_monitortimeout,
+ { "Monitor Timeout (ms)", "btl2cap.monitortimeout",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "S-frame transmission interval (milliseconds)", HFILL }
+ },
+ { &hf_btl2cap_option_mps,
+ { "MPS", "btl2cap.mps",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum PDU Payload Size", HFILL }
+ },
+ { &hf_btl2cap_option_fcs,
+ { "FCS", "btl2cap.option_fcs",
+ FT_UINT16, BASE_HEX, VALS(option_fcs_vals), 0x0,
+ "Frame Check Sequence", HFILL }
+ },
+ { &hf_btl2cap_option_window,
+ { "Extended Window Size", "btl2cap.option_window",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_option,
+ { "Configuration Parameter Option", "btl2cap.conf_param_option",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_control_sar,
+ { "Segmentation and reassembly", "btl2cap.control_sar",
+ FT_UINT16, BASE_HEX, VALS(control_sar_vals), 0xC000,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_control_reqseq,
+ { "ReqSeq", "btl2cap.control_reqseq",
+ FT_UINT16, BASE_DEC, NULL, 0x3F00,
+ "Request Sequence Number", HFILL }
+ },
+ { &hf_btl2cap_control_txseq,
+ { "TxSeq", "btl2cap.control_txseq",
+ FT_UINT16, BASE_DEC, NULL, 0x007E,
+ "Transmitted Sequence Number", HFILL }
+ },
+ { &hf_btl2cap_control_retransmissiondisable,
+ { "R", "btl2cap.control_retransmissiondisable",
+ FT_UINT16, BASE_HEX, NULL, 0x0080,
+ "Retransmission Disable", HFILL }
+ },
+ { &hf_btl2cap_control_supervisory,
+ { "S", "btl2cap.control_supervisory",
+ FT_UINT16, BASE_HEX, VALS(control_supervisory_vals), 0x000C,
+ "Supervisory Function", HFILL }
+ },
+ { &hf_btl2cap_control_type,
+ { "Frame Type", "btl2cap.control_type",
+ FT_UINT16, BASE_HEX, VALS(control_type_vals), 0x0001,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_control,
+ { "Control field", "btl2cap.control",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_fcs,
+ { "FCS", "btl2cap.fcs",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Frame Check Sequence", HFILL }
+ },
+ { &hf_btl2cap_sdulength,
+ { "SDU Length", "btl2cap.sdulength",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_btl2cap_reassembled_in,
+ { "This SDU is reassembled in frame", "btl2cap.reassembled_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "This SDU is reassembled in frame #", HFILL }
+ },
+ { &hf_btl2cap_continuation_to,
+ { "This is a continuation to the SDU in frame", "btl2cap.continuation_to",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "This is a continuation to the SDU in frame #", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btl2cap,
+ &ett_btl2cap_cmd,
+ &ett_btl2cap_option,
+ &ett_btl2cap_extfeatures,
+ &ett_btl2cap_fixedchans,
+ &ett_btl2cap_control
+ };
+
+ /* Register the protocol name and description */
+ proto_btl2cap = proto_register_protocol("Bluetooth L2CAP Protocol", "L2CAP", "btl2cap");
+
+ register_dissector("btl2cap", dissect_btl2cap, proto_btl2cap);
+
+ /* subdissector code */
+ l2cap_psm_dissector_table = register_dissector_table("btl2cap.psm", "L2CAP PSM", FT_UINT16, BASE_HEX);
+ l2cap_service_dissector_table = register_dissector_table("btl2cap.service", "L2CAP Service", FT_UINT16, BASE_HEX);
+ l2cap_cid_dissector_table = register_dissector_table("btl2cap.cid", "L2CAP CID", FT_UINT16, BASE_HEX);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btl2cap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ cid_to_psm_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btl2cap scid to psm");
+ psm_to_service_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "btl2cap psm to service uuid");
}
void
proto_reg_handoff_btl2cap(void)
{
- /* tap into the btsdp dissector to look for l2cap PSM infomation that
- helps us determine the type of l2cap payload, i.e. which service is
- using the PSM channel so we know which sub-dissector to call */
- register_tap_listener("btsdp", NULL, NULL, TL_IS_DISSECTOR_HELPER, NULL, btl2cap_sdp_tap_packet, NULL);
+ /* tap into the btsdp dissector to look for l2cap PSM infomation that
+ helps us determine the type of l2cap payload, i.e. which service is
+ using the PSM channel so we know which sub-dissector to call */
+ register_tap_listener("btsdp", NULL, NULL, TL_IS_DISSECTOR_HELPER, NULL, btl2cap_sdp_tap_packet, NULL);
}
diff --git a/epan/dissectors/packet-btl2cap.h b/epan/dissectors/packet-btl2cap.h
index 53c0ac38a2..ccb65d626a 100644
--- a/epan/dissectors/packet-btl2cap.h
+++ b/epan/dissectors/packet-btl2cap.h
@@ -24,31 +24,31 @@
#ifndef __PACKET_BTL2CAP_H__
#define __PACKET_BTL2CAP_H__
-#define BTL2CAP_PSM_SDP 0x0001
-#define BTL2CAP_PSM_RFCOMM 0x0003
-#define BTL2CAP_PSM_BNEP 0x000f
-#define BTL2CAP_PSM_HID_CTRL 0x0011
-#define BTL2CAP_PSM_HID_INTR 0x0013
-#define BTL2CAP_PSM_AVCTP_CTRL 0x0017
-#define BTL2CAP_PSM_AVDTP 0x0019
-#define BTL2CAP_PSM_AVCTP_BRWS 0x001b
+#define BTL2CAP_PSM_SDP 0x0001
+#define BTL2CAP_PSM_RFCOMM 0x0003
+#define BTL2CAP_PSM_BNEP 0x000f
+#define BTL2CAP_PSM_HID_CTRL 0x0011
+#define BTL2CAP_PSM_HID_INTR 0x0013
+#define BTL2CAP_PSM_AVCTP_CTRL 0x0017
+#define BTL2CAP_PSM_AVDTP 0x0019
+#define BTL2CAP_PSM_AVCTP_BRWS 0x001b
#define BTL2CAP_DYNAMIC_PSM_START 0x1000
-#define BTL2CAP_FIXED_CID_NULL 0x0000
-#define BTL2CAP_FIXED_CID_SIGNAL 0x0001
-#define BTL2CAP_FIXED_CID_CONNLESS 0x0002
-#define BTL2CAP_FIXED_CID_AMP_MAN 0x0003
-#define BTL2CAP_FIXED_CID_AMP_TEST 0x003F
-#define BTL2CAP_FIXED_CID_MAX 0x0040
+#define BTL2CAP_FIXED_CID_NULL 0x0000
+#define BTL2CAP_FIXED_CID_SIGNAL 0x0001
+#define BTL2CAP_FIXED_CID_CONNLESS 0x0002
+#define BTL2CAP_FIXED_CID_AMP_MAN 0x0003
+#define BTL2CAP_FIXED_CID_AMP_TEST 0x003F
+#define BTL2CAP_FIXED_CID_MAX 0x0040
/* This structure is passed to higher layer protocols through
* pinfo->private_data so that they can track "conversations" based on
* chandle, cid and direction
*/
typedef struct _btl2cap_data_t {
- guint16 chandle; /* only low 12 bits used */
- guint16 cid;
+ guint16 chandle; /* only low 12 bits used */
+ guint16 cid;
} btl2cap_data_t;
#endif
diff --git a/epan/dissectors/packet-btobex.c b/epan/dissectors/packet-btobex.c
index 7500f43f71..34c4a680d5 100644
--- a/epan/dissectors/packet-btobex.c
+++ b/epan/dissectors/packet-btobex.c
@@ -68,6 +68,7 @@ static int hf_btobex_fragment_error = -1;
static int hf_btobex_fragment_count = -1;
static int hf_btobex_reassembled_in = -1;
static int hf_btobex_reassembled_length = -1;
+
static gint ett_btobex_fragment = -1;
static gint ett_btobex_fragments = -1;
@@ -102,8 +103,8 @@ static dissector_handle_t xml_handle;
static dissector_handle_t data_handle;
typedef struct _ext_value_string {
- guint8 value[16];
- const gchar *strptr;
+ guint8 value[16];
+ const gchar *strptr;
} ext_value_string;
static const ext_value_string target_vals[] = {
@@ -131,11 +132,6 @@ static const value_string version_vals[] = {
{ 0, NULL }
};
-static const true_false_string true_false = {
- "True",
- "False"
-};
-
#define BTOBEX_CODE_VALS_CONNECT 0x00
#define BTOBEX_CODE_VALS_DISCONNECT 0x01
#define BTOBEX_CODE_VALS_PUT 0x02
@@ -192,6 +188,7 @@ static const value_string code_vals[] = {
{ BTOBEX_CODE_VALS_ABORT, "Abort" },
{ 0, NULL }
};
+static value_string_ext(code_vals_ext) = VALUE_STRING_EXT_INIT(code_vals);
static const value_string header_id_vals[] = {
{ 0x01, "Name" },
@@ -229,555 +226,557 @@ static const value_string header_id_vals[] = {
{ 0x3f, "User Defined" },
{ 0, NULL }
};
+static value_string_ext header_id_vals_ext = VALUE_STRING_EXT_INIT(header_id_vals);
static void
defragment_init(void)
{
- fragment_table_init(&fragment_table);
- reassembled_table_init(&reassembled_table);
+ fragment_table_init(&fragment_table);
+ reassembled_table_init(&reassembled_table);
}
static int
is_ascii_str(const guint8 *str, int length)
{
- int i;
+ int i;
- if( (length < 1) || (str[length-1] != '\0') )
- return 0;
+ if ((length < 1) || (str[length-1] != '\0'))
+ return 0;
- for(i=0; i<length-1; i++) {
- if( (str[i] < 0x20) && (str[i] != 0x0a) ) /* not strict ascii */
- break;
- }
+ for(i=0; i<length-1; i++) {
+ if ((str[i] < 0x20) && (str[i] != 0x0a)) /* not strict ascii */
+ break;
+ }
- if(i<(length-1))
- return 0;
+ if (i < (length-1))
+ return 0;
- return 1;
+ return 1;
}
static int
display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, char **data)
{
- char *str, *p;
- int len;
- int charoffset;
- guint16 character;
-
- /* display a unicode string from the tree and return new offset */
- /*
- * Get the length of the string.
- */
- len = 0;
- while (tvb_get_ntohs(tvb, offset + len) != '\0')
- len += 2;
-
- len += 2; /* count the '\0' too */
-
- /*
- * Allocate a buffer for the string; "len" is the length in
- * bytes, not the length in characters.
- */
- str = ep_alloc(len/2);
-
- /* - this assumes the string is just ISO 8859-1 */
- charoffset = offset;
- p = str;
- while ((character = tvb_get_ntohs(tvb, charoffset)) != '\0') {
- *p++ = (char) character;
- charoffset += 2;
- }
- *p = '\0';
-
- if(!is_ascii_str(str, len/2)) {
- *str = '\0';
- }
-
- proto_tree_add_string(tree, hf_hdr_val_unicode, tvb, offset, len, str);
-
- if (data)
- *data = str;
-
- return offset+len;
+ char *str, *p;
+ int len;
+ int charoffset;
+ guint16 character;
+
+ /* display a unicode string from the tree and return new offset */
+ /*
+ * Get the length of the string.
+ */
+ len = 0;
+ while (tvb_get_ntohs(tvb, offset + len) != '\0')
+ len += 2;
+
+ len += 2; /* count the '\0' too */
+
+ /*
+ * Allocate a buffer for the string; "len" is the length in
+ * bytes, not the length in characters.
+ */
+ str = ep_alloc(len/2);
+
+ /* - this assumes the string is just ISO 8859-1 */
+ charoffset = offset;
+ p = str;
+ while ((character = tvb_get_ntohs(tvb, charoffset)) != '\0') {
+ *p++ = (char) character;
+ charoffset += 2;
+ }
+ *p = '\0';
+
+ if (!is_ascii_str(str, len/2)) {
+ *str = '\0';
+ }
+
+ proto_tree_add_string(tree, hf_hdr_val_unicode, tvb, offset, len, str);
+
+ if (data)
+ *data = str;
+
+ return offset+len;
}
static int
dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- proto_tree *hdrs_tree=NULL;
- proto_item *hdrs=NULL;
- proto_tree *hdr_tree=NULL;
- proto_item *hdr=NULL;
- proto_item *handle_item;
- gint item_length = -1;
- guint8 hdr_id, i;
-
- if(tvb_length_remaining(tvb, offset)>0) {
- hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
- hdrs_tree=proto_item_add_subtree(hdrs, ett_btobex_hdrs);
- }
- else {
- return offset;
- }
-
- while(tvb_length_remaining(tvb, offset)>0) {
- hdr_id = tvb_get_guint8(tvb, offset);
-
- switch(0xC0 & hdr_id)
- {
- case 0x00: /* null terminated unicode */
- item_length = tvb_get_ntohs(tvb, offset+1);
- break;
- case 0x40: /* byte sequence */
- item_length = tvb_get_ntohs(tvb, offset+1);
- break;
- case 0x80: /* 1 byte */
- item_length = 2;
- break;
- case 0xc0: /* 4 bytes */
- item_length = 5;
- break;
- }
-
- hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s", val_to_str(hdr_id, header_id_vals, "Unknown"));
- hdr_tree=proto_item_add_subtree(hdr, ett_btobex_hdr);
-
- proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN);
-
- offset++;
-
- switch(0xC0 & hdr_id)
- {
- case 0x00: /* null terminated unicode */
- {
- proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
-
- if( (item_length - 3) > 0 ) {
- char *str;
-
- display_unicode_string(tvb, hdr_tree, offset, &str);
- proto_item_append_text(hdr_tree, " (\"%s\")", str);
- col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
- }
- else {
- col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
- }
-
- offset += item_length - 3;
- }
- break;
- case 0x40: /* byte sequence */
- proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
-
- handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA);
-
- if( ((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19) ) { /* target or who */
- for( i=0; target_vals[i].strptr != NULL; i++) {
- if( tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0 ) {
- proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
- proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
- col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
- }
- }
- }
-
- if( !tvb_strneql(tvb, offset, "<?xml", 5) )
- {
- tvbuff_t* next_tvb = tvb_new_subset(tvb, offset, -1, -1);
-
- call_dissector(xml_handle, next_tvb, pinfo, tree);
- }
- else if(is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
- {
- proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
- col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
- }
-
- offset += item_length - 3;
- break;
- case 0x80: /* 1 byte */
- proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
- proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
- break;
- case 0xc0: /* 4 bytes */
- proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
- proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN);
- offset += 4;
- break;
- default:
- break;
- }
- }
-
- return offset;
+ proto_tree *hdrs_tree = NULL;
+ proto_tree *hdr_tree = NULL;
+ proto_item *hdr = NULL;
+ proto_item *handle_item;
+ gint item_length = -1;
+ guint8 hdr_id, i;
+
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ proto_item *hdrs;
+ hdrs = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
+ hdrs_tree = proto_item_add_subtree(hdrs, ett_btobex_hdrs);
+ }
+ else {
+ return offset;
+ }
+
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ hdr_id = tvb_get_guint8(tvb, offset);
+
+ switch(0xC0 & hdr_id)
+ {
+ case 0x00: /* null terminated unicode */
+ item_length = tvb_get_ntohs(tvb, offset+1);
+ break;
+ case 0x40: /* byte sequence */
+ item_length = tvb_get_ntohs(tvb, offset+1);
+ break;
+ case 0x80: /* 1 byte */
+ item_length = 2;
+ break;
+ case 0xc0: /* 4 bytes */
+ item_length = 5;
+ break;
+ }
+
+ hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s",
+ val_to_str_ext_const(hdr_id, &header_id_vals_ext, "Unknown"));
+ hdr_tree = proto_item_add_subtree(hdr, ett_btobex_hdr);
+
+ proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ offset++;
+
+ switch(0xC0 & hdr_id)
+ {
+ case 0x00: /* null terminated unicode */
+ {
+ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ if ((item_length - 3) > 0) {
+ char *str;
+
+ display_unicode_string(tvb, hdr_tree, offset, &str);
+ proto_item_append_text(hdr_tree, " (\"%s\")", str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
+ }
+ else {
+ col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
+ }
+
+ offset += item_length - 3;
+ }
+ break;
+ case 0x40: /* byte sequence */
+ proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA);
+
+ if (((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19)) { /* target or who */
+ for(i=0; target_vals[i].strptr != NULL; i++) {
+ if (tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0) {
+ proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
+ proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
+ }
+ }
+ }
+
+ if (!tvb_strneql(tvb, offset, "<?xml", 5))
+ {
+ tvbuff_t* next_tvb = tvb_new_subset_remaining(tvb, offset);
+
+ call_dissector(xml_handle, next_tvb, pinfo, tree);
+ }
+ else if (is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
+ {
+ proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
+ }
+
+ offset += item_length - 3;
+ break;
+ case 0x80: /* 1 byte */
+ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ break;
+ case 0xc0: /* 4 bytes */
+ proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return offset;
}
static void
dissect_btobex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
- fragment_data *frag_msg = NULL;
- gboolean save_fragmented, complete;
- tvbuff_t* new_tvb = NULL;
- tvbuff_t* next_tvb = NULL;
- guint32 no_of_segments = 0;
- int offset=0;
-
- save_fragmented = pinfo->fragmented;
-
- frag_msg = NULL;
- complete = FALSE;
-
- if( fragment_get(pinfo, pinfo->p2p_dir, fragment_table) ) {
- /* not the first fragment */
- frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
- fragment_table, reassembled_table, tvb_length(tvb), TRUE);
-
- new_tvb = process_reassembled_data(tvb, 0, pinfo,
- "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
-
- pinfo->fragmented = TRUE;
- }
- else {
- if(tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1)) {
- /* first fragment in a sequence */
- no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb);
- if ( tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb)))
- no_of_segments++;
-
- frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
- fragment_table, reassembled_table, tvb_length(tvb), TRUE);
-
- fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1);
-
- new_tvb = process_reassembled_data(tvb, 0, pinfo,
- "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
-
- pinfo->fragmented = TRUE;
- }
- else if( tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1) ) {
- /* non-fragmented */
- complete = TRUE;
- pinfo->fragmented = FALSE;
- }
- }
-
- if (new_tvb) { /* take it all */
- next_tvb = new_tvb;
- complete = TRUE;
- }
- else { /* make a new subset */
- next_tvb = tvb_new_subset(tvb, offset, -1, -1);
- }
-
- if( complete ) {
- guint8 code, final_flag;
-
- /* fully dissectable packet ready */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX");
-
- ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, ENC_NA);
- st = proto_item_add_subtree(ti, ett_btobex);
-
- /* op/response code */
- code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK;
- final_flag = tvb_get_guint8(next_tvb, offset) & 0x80;
-
- switch (pinfo->p2p_dir) {
-
- case P2P_DIR_SENT:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
- break;
-
- case P2P_DIR_RECV:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
- break;
-
- case P2P_DIR_UNKNOWN:
- break;
-
- default:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
- pinfo->p2p_dir);
- break;
- }
-
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
- val_to_str(code, code_vals, "Unknown"));
-
- if( (code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT)) {
- proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- if (pinfo->p2p_dir == P2P_DIR_SENT || pinfo->p2p_dir == P2P_DIR_RECV) {
- last_opcode[pinfo->p2p_dir] = code;
- }
- }
- else {
- proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- }
- proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- /* length */
- proto_tree_add_item(st, hf_length, next_tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
-
- switch(code)
- {
- case BTOBEX_CODE_VALS_CONNECT:
- proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- break;
-
- case BTOBEX_CODE_VALS_PUT:
- case BTOBEX_CODE_VALS_GET:
- col_append_fstr(pinfo->cinfo, COL_INFO, " %s", final_flag==0x80?"final":"continue");
- break;
-
- case BTOBEX_CODE_VALS_SET_PATH:
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
- break;
-
- case BTOBEX_CODE_VALS_DISCONNECT:
- case BTOBEX_CODE_VALS_ABORT:
- break;
-
- default:
- {
- guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01];
-
- if(response_opcode == BTOBEX_CODE_VALS_CONNECT) {
- proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
- offset++;
-
- proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- }
- }
- break;
- }
-
- dissect_headers(st, next_tvb, offset, pinfo);
- }
- else
- {
- /* packet fragment */
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd");
-
- call_dissector(data_handle, next_tvb, pinfo, tree);
- }
-
- pinfo->fragmented = save_fragmented;
+ proto_item *ti;
+ proto_tree *st;
+ fragment_data *frag_msg = NULL;
+ gboolean save_fragmented, complete;
+ tvbuff_t* new_tvb = NULL;
+ tvbuff_t* next_tvb = NULL;
+ guint32 no_of_segments = 0;
+ int offset = 0;
+
+ save_fragmented = pinfo->fragmented;
+
+ frag_msg = NULL;
+ complete = FALSE;
+
+ if (fragment_get(pinfo, pinfo->p2p_dir, fragment_table)) {
+ /* not the first fragment */
+ frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
+ fragment_table, reassembled_table, tvb_length(tvb), TRUE);
+
+ new_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
+
+ pinfo->fragmented = TRUE;
+ }
+ else {
+ if (tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1)) {
+ /* first fragment in a sequence */
+ no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb);
+ if (tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb)))
+ no_of_segments++;
+
+ frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
+ fragment_table, reassembled_table, tvb_length(tvb), TRUE);
+
+ fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1);
+
+ new_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);
+
+ pinfo->fragmented = TRUE;
+ }
+ else if (tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1)) {
+ /* non-fragmented */
+ complete = TRUE;
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (new_tvb) { /* take it all */
+ next_tvb = new_tvb;
+ complete = TRUE;
+ }
+ else { /* make a new subset */
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+ }
+
+ if (complete) {
+ guint8 code, final_flag;
+
+ /* fully dissectable packet ready */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX");
+
+ ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, ENC_NA);
+ st = proto_item_add_subtree(ti, ett_btobex);
+
+ /* op/response code */
+ code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK;
+ final_flag = tvb_get_guint8(next_tvb, offset) & 0x80;
+
+ switch (pinfo->p2p_dir)
+ {
+ case P2P_DIR_SENT:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
+ break;
+
+ case P2P_DIR_RECV:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
+ break;
+
+ case P2P_DIR_UNKNOWN:
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
+ pinfo->p2p_dir);
+ break;
+ }
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str_ext_const(code, &code_vals_ext, "Unknown"));
+
+ if ((code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT)) {
+ proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ if (pinfo->p2p_dir == P2P_DIR_SENT || pinfo->p2p_dir == P2P_DIR_RECV) {
+ last_opcode[pinfo->p2p_dir] = code;
+ }
+ }
+ else {
+ proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ }
+ proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ /* length */
+ proto_tree_add_item(st, hf_length, next_tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ switch(code)
+ {
+ case BTOBEX_CODE_VALS_CONNECT:
+ proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+
+ case BTOBEX_CODE_VALS_PUT:
+ case BTOBEX_CODE_VALS_GET:
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", (final_flag == 0x80) ? "final" : "continue");
+ break;
+
+ case BTOBEX_CODE_VALS_SET_PATH:
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ break;
+
+ case BTOBEX_CODE_VALS_DISCONNECT:
+ case BTOBEX_CODE_VALS_ABORT:
+ break;
+
+ default:
+ {
+ guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01];
+
+ if (response_opcode == BTOBEX_CODE_VALS_CONNECT) {
+ proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+
+ proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ }
+ break;
+ }
+
+ dissect_headers(st, next_tvb, offset, pinfo);
+ }
+ else
+ {
+ /* packet fragment */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment",
+ (pinfo->p2p_dir==P2P_DIR_SENT) ? "Sent" : "Rcvd");
+
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+
+ pinfo->fragmented = save_fragmented;
}
void
proto_register_btobex(void)
{
- static hf_register_info hf[] = {
- {&hf_opcode,
- {"Opcode", "btobex.opcode",
- FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
- "Request Opcode", HFILL}
- },
- {&hf_response_code,
- {"Response Code", "btobex.resp_code",
- FT_UINT8, BASE_HEX, VALS(code_vals), BTOBEX_CODE_VALS_MASK,
- NULL, HFILL}
- },
- {&hf_final_flag,
- {"Final Flag", "btobex.final_flag",
- FT_BOOLEAN, 8, TFS(&true_false), 0x80,
- NULL, HFILL}
- },
- {&hf_length,
- {"Packet Length", "btobex.pkt_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- NULL, HFILL}
- },
- {&hf_version,
- {"Version", "btobex.version",
- FT_UINT8, BASE_HEX, VALS(version_vals), 0x00,
- "Obex Protocol Version", HFILL}
- },
- {&hf_flags,
- {"Flags", "btobex.flags",
- FT_UINT8, BASE_HEX, NULL, 0x00,
- NULL, HFILL}
- },
- {&hf_constants,
- {"Constants", "btobex.constants",
- FT_UINT8, BASE_HEX, NULL, 0x00,
- NULL, HFILL}
- },
- {&hf_max_pkt_len,
- {"Max. Packet Length", "btobex.max_pkt_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- NULL, HFILL}
- },
- {&hf_set_path_flags_0,
- {"Go back one folder (../) first", "btobex.set_path_flags_0",
- FT_BOOLEAN, 8, TFS(&true_false), 0x01,
- NULL, HFILL}
- },
- {&hf_set_path_flags_1,
- {"Do not create folder, if not existing", "btobex.set_path_flags_1",
- FT_BOOLEAN, 8, TFS(&true_false), 0x02,
- NULL, HFILL}
- },
- {&hf_hdr_id,
- {"Header Id", "btobex.hdr_id",
- FT_UINT8, BASE_HEX, VALS(header_id_vals), 0x00,
- NULL, HFILL}
- },
- {&hf_hdr_length,
- {"Length", "btobex.pkt_hdr_len",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Header Length", HFILL}
- },
- {&hf_hdr_val_unicode,
- { "Value", "btobex.pkt_hdr_val_uc",
- FT_STRING, BASE_NONE, NULL, 0,
- "Unicode Value", HFILL }
- },
- {&hf_hdr_val_byte_seq,
- {"Value", "btobex.hdr_val_byte_seq",
- FT_BYTES, BASE_NONE, NULL, 0,
- "Byte Value", HFILL}
- },
- {&hf_hdr_val_byte,
- {"Value", "btobex.hdr_val_byte",
- FT_UINT8, BASE_HEX, NULL, 0,
- "Byte Sequence Value", HFILL}
- },
- {&hf_hdr_val_long,
- {"Value", "btobex.hdr_val_long",
- FT_UINT32, BASE_DEC, NULL, 0,
- "4-byte Value", HFILL}
- },
-
- /* for fragmentation */
- { &hf_btobex_fragment_overlap,
- { "Fragment overlap", "btobex.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Fragment overlaps with other fragments", HFILL }
- },
- { &hf_btobex_fragment_overlap_conflict,
- { "Conflicting data in fragment overlap", "btobex.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Overlapping fragments contained conflicting data", HFILL }
- },
- { &hf_btobex_fragment_multiple_tails,
- { "Multiple tail fragments found", "btobex.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Several tails were found when defragmenting the packet", HFILL }
- },
- { &hf_btobex_fragment_too_long_fragment,
- { "Fragment too long", "btobex.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "Fragment contained data past end of packet", HFILL }
- },
- { &hf_btobex_fragment_error,
- { "Defragmentation error", "btobex.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "Defragmentation error due to illegal fragments", HFILL }
- },
- { &hf_btobex_fragment_count,
- { "Fragment count", "btobex.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
- NULL, HFILL }
- },
- { &hf_btobex_fragment,
- { "OBEX Fragment", "btobex.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "btobex Fragment", HFILL }
- },
- { &hf_btobex_fragments,
- { "OBEX Fragments", "btobex.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
- "btobex Fragments", HFILL }
- },
- { &hf_btobex_reassembled_in,
- { "Reassembled OBEX in frame", "btobex.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "This OBEX frame is reassembled in this frame", HFILL }
- },
- { &hf_btobex_reassembled_length,
- { "Reassembled OBEX length", "btobex.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
- "The total length of the reassembled payload", HFILL }
- }
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btobex,
- &ett_btobex_hdrs,
- &ett_btobex_hdr,
- &ett_btobex_fragment,
- &ett_btobex_fragments
- };
-
- proto_btobex = proto_register_protocol("Bluetooth OBEX Protocol", "OBEX", "btobex");
-
- register_dissector("btobex", dissect_btobex, proto_btobex);
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_btobex, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- register_init_routine(&defragment_init);
+ static hf_register_info hf[] = {
+ { &hf_opcode,
+ { "Opcode", "btobex.opcode",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &code_vals_ext, BTOBEX_CODE_VALS_MASK,
+ "Request Opcode", HFILL}
+ },
+ { &hf_response_code,
+ { "Response Code", "btobex.resp_code",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &code_vals_ext, BTOBEX_CODE_VALS_MASK,
+ NULL, HFILL}
+ },
+ { &hf_final_flag,
+ { "Final Flag", "btobex.final_flag",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL}
+ },
+ { &hf_length,
+ { "Packet Length", "btobex.pkt_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL}
+ },
+ { &hf_version,
+ { "Version", "btobex.version",
+ FT_UINT8, BASE_HEX, VALS(version_vals), 0x00,
+ "Obex Protocol Version", HFILL}
+ },
+ { &hf_flags,
+ { "Flags", "btobex.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_constants,
+ { "Constants", "btobex.constants",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_max_pkt_len,
+ { "Max. Packet Length", "btobex.max_pkt_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL}
+ },
+ { &hf_set_path_flags_0,
+ { "Go back one folder (../) first", "btobex.set_path_flags_0",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL}
+ },
+ { &hf_set_path_flags_1,
+ { "Do not create folder, if not existing", "btobex.set_path_flags_1",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL}
+ },
+ { &hf_hdr_id,
+ { "Header Id", "btobex.hdr_id",
+ FT_UINT8, BASE_HEX|BASE_EXT_STRING, &header_id_vals_ext, 0x00,
+ NULL, HFILL}
+ },
+ { &hf_hdr_length,
+ { "Length", "btobex.pkt_hdr_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Header Length", HFILL}
+ },
+ { &hf_hdr_val_unicode,
+ { "Value", "btobex.pkt_hdr_val_uc",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "Unicode Value", HFILL }
+ },
+ { &hf_hdr_val_byte_seq,
+ { "Value", "btobex.hdr_val_byte_seq",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Byte Value", HFILL}
+ },
+ { &hf_hdr_val_byte,
+ { "Value", "btobex.hdr_val_byte",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Byte Sequence Value", HFILL}
+ },
+ { &hf_hdr_val_long,
+ { "Value", "btobex.hdr_val_long",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "4-byte Value", HFILL}
+ },
+
+ /* for fragmentation */
+ { &hf_btobex_fragment_overlap,
+ { "Fragment overlap", "btobex.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }
+ },
+ { &hf_btobex_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "btobex.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }
+ },
+ { &hf_btobex_fragment_multiple_tails,
+ { "Multiple tail fragments found", "btobex.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }
+ },
+ { &hf_btobex_fragment_too_long_fragment,
+ { "Fragment too long", "btobex.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }
+ },
+ { &hf_btobex_fragment_error,
+ { "Defragmentation error", "btobex.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }
+ },
+ { &hf_btobex_fragment_count,
+ { "Fragment count", "btobex.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_btobex_fragment,
+ { "OBEX Fragment", "btobex.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "btobex Fragment", HFILL }
+ },
+ { &hf_btobex_fragments,
+ { "OBEX Fragments", "btobex.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "btobex Fragments", HFILL }
+ },
+ { &hf_btobex_reassembled_in,
+ { "Reassembled OBEX in frame", "btobex.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This OBEX frame is reassembled in this frame", HFILL }
+ },
+ { &hf_btobex_reassembled_length,
+ { "Reassembled OBEX length", "btobex.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The total length of the reassembled payload", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btobex,
+ &ett_btobex_hdrs,
+ &ett_btobex_hdr,
+ &ett_btobex_fragment,
+ &ett_btobex_fragments
+ };
+
+ proto_btobex = proto_register_protocol("Bluetooth OBEX Protocol", "OBEX", "btobex");
+
+ register_dissector("btobex", dissect_btobex, proto_btobex);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btobex, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(&defragment_init);
}
void
proto_reg_handoff_btobex(void)
{
- dissector_handle_t btobex_handle;
-
- btobex_handle = find_dissector("btobex");
-
- /* register in rfcomm and l2cap the profiles/services this dissector should handle */
- dissector_add_uint("btrfcomm.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
-
- dissector_add_uint("btl2cap.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
- dissector_add_uint("btl2cap.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
-
- xml_handle = find_dissector("xml");
- data_handle = find_dissector("data");
+ dissector_handle_t btobex_handle;
+
+ btobex_handle = find_dissector("btobex");
+
+ /* register in rfcomm and l2cap the profiles/services this dissector should handle */
+ dissector_add_uint("btrfcomm.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
+
+ dissector_add_uint("btl2cap.service", BTSDP_OPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_FTP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BPP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BPP_STATUS_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_RESPONDER_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_AUTO_ARCH_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_BIP_REF_OBJ_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_PCE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_PSE_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_PBAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_ACCESS_SRV_SERVICE_UUID, btobex_handle);
+ dissector_add_uint("btl2cap.service", BTSDP_MAP_NOIYFY_SRV_SERVICE_UUID, btobex_handle);
+
+ xml_handle = find_dissector("xml");
+ data_handle = find_dissector("data");
}
diff --git a/epan/dissectors/packet-btrfcomm.c b/epan/dissectors/packet-btrfcomm.c
index 3ad37dfbd6..459803dfd1 100644
--- a/epan/dissectors/packet-btrfcomm.c
+++ b/epan/dissectors/packet-btrfcomm.c
@@ -105,314 +105,315 @@ static emem_tree_t *dlci_table;
dissector_table_t rfcomm_service_dissector_table;
typedef struct _dlci_stream_t {
- int len;
- int current;
- int is_escaped;
- int mode;
- guint8 *stream_buf;
+ int len;
+ int current;
+ int is_escaped;
+ int mode;
+ guint8 *stream_buf;
} dlci_stream_t;
typedef struct _dlci_state_t {
- guint32 service;
- char do_credit_fc;
+ guint32 service;
+ char do_credit_fc;
} dlci_state_t;
static dissector_handle_t data_handle;
static dissector_handle_t ppp_handle;
static const value_string vs_ctl_pn_i[] = {
- {0x0, "use UIH Frames"},
- /* specified by 07.10, but not used by RFCOMM
- {0x1, "use UI Frames"},
- {0x2, "use I Frames"},
- */
- {0, NULL}
+ {0x0, "use UIH Frames"},
+#if 0 /* specified by 07.10, but not used by RFCOMM */
+ {0x1, "use UI Frames"},
+ {0x2, "use I Frames"},
+#endif
+ {0, NULL}
};
static const value_string vs_ctl_pn_cl[] = {
- {0x0, "no credit based flow control scheme"},
- {0xe, "support of credit based flow control scheme (resp)"},
- {0xf, "support of credit based flow control scheme (req)"},
- /* specified by 07.10. Redefined by RFCOMM
- {0x0, "type 1 (unstructured octet stream)"},
- {0x1, "type 2 (unstructured octet stream with flow control)"},
- {0x2, "type 3 (uninterruptible framed data)"},
- {0x3, "type 4 (interruptible framed data)"},
- */
- {0, NULL}
+ {0x0, "no credit based flow control scheme"},
+ {0xe, "support of credit based flow control scheme (resp)"},
+ {0xf, "support of credit based flow control scheme (req)"},
+#if 0 /* specified by 07.10. Redefined by RFCOMM */
+ {0x0, "type 1 (unstructured octet stream)"},
+ {0x1, "type 2 (unstructured octet stream with flow control)"},
+ {0x2, "type 3 (uninterruptible framed data)"},
+ {0x3, "type 4 (interruptible framed data)"},
+#endif
+ {0, NULL}
};
static const value_string vs_frame_type[] = {
- /* masked 0xef */
- {0x2f, "Set Asynchronous Balanced Mode (SABM)"},
- {0x63, "Unnumbered Acknowledgement (UA)"},
- {0x0f, "Disconnected Mode (DM)"},
- {0x43, "Disconnect (DISC)"},
- {0xef, "Unnumbered Information with Header check (UIH)"},
- /* specified by 07.10, but not used by RFCOMM
- {0x03, "Unnumbered Information (UI)"},
- */
+ /* masked 0xef */
+ {0x2f, "Set Asynchronous Balanced Mode (SABM)"},
+ {0x63, "Unnumbered Acknowledgement (UA)"},
+ {0x0f, "Disconnected Mode (DM)"},
+ {0x43, "Disconnect (DISC)"},
+ {0xef, "Unnumbered Information with Header check (UIH)"},
+#if 0 /* specified by 07.10, but not used by RFCOMM */
+ {0x03, "Unnumbered Information (UI)"},
+#endif
{0, NULL}
};
static const value_string vs_frame_type_short[] = {
- /* masked 0xef */
- {0x2f, "SABM"},
- {0x63, "UA"},
- {0x0f, "DM"},
- {0x43, "DISC"},
- {0xef, "UIH"},
- /* specified by 07.10, but not used by RFCOMM
- {0x03, "UI"},
- */
+ /* masked 0xef */
+ {0x2f, "SABM"},
+ {0x63, "UA"},
+ {0x0f, "DM"},
+ {0x43, "DISC"},
+ {0xef, "UIH"},
+#if 0 /* specified by 07.10, but not used by RFCOMM */
+ {0x03, "UI"},
+#endif
{0, NULL}
};
static const value_string vs_ctl[] = {
/* masked 0xfc */
- {0x20, "DLC parameter negotiation (PN)"},
- {0x08, "Test Command (Test)"},
- {0x28, "Flow Control On Command (FCon)"},
- {0x18, "Flow Control Off Command (FCoff)"},
- {0x38, "Modem Status Command (MSC)"},
- {0x04, "Non Supported Command Response (NSC)"},
- {0x24, "Remote Port Negotiation Command (RPN)"},
- {0x14, "Remote Line Status Command (RLS)"},
- /* Specified by 07.10, but not used by RFCOMM
- {0x10, "Power Saving Control (PSC)"},
- {0x30, "Multiplexer close down (CLD)"},
- {0x34, "Service Negotiation Command (SNC)"},
- */
- /* old
- {0x80, "DLC parameter negotiation (PN)"},
- {0x20, "Test Command (Test)"},
- {0xa0, "Flow Control On Command (FCon)"},
- {0x60, "Flow Control Off Command (FCoff)"},
- {0xe0, "Modem Status Command (MSC)"},
- {0x10, "Non Supported Command Response (NSC)"},
- {0x90, "Remote Port Negotiation Command (RPN)"},
- {0x50, "Remote Line Status Command (RLS)"},
- {0x40, "Power Saving Control (PSC)"},
- {0xc0, "Multiplexer close down (CLD)"},
- {0xd0, "Service Negotiation Command (SNC)"},
- */
- {0x0, NULL}
+ {0x20, "DLC parameter negotiation (PN)"},
+ {0x08, "Test Command (Test)"},
+ {0x28, "Flow Control On Command (FCon)"},
+ {0x18, "Flow Control Off Command (FCoff)"},
+ {0x38, "Modem Status Command (MSC)"},
+ {0x04, "Non Supported Command Response (NSC)"},
+ {0x24, "Remote Port Negotiation Command (RPN)"},
+ {0x14, "Remote Line Status Command (RLS)"},
+#if 0 /* Specified by 07.10, but not used by RFCOMM */
+ {0x10, "Power Saving Control (PSC)"},
+ {0x30, "Multiplexer close down (CLD)"},
+ {0x34, "Service Negotiation Command (SNC)"},
+#endif
+#if 0 /* old */
+ {0x80, "DLC parameter negotiation (PN)"},
+ {0x20, "Test Command (Test)"},
+ {0xa0, "Flow Control On Command (FCon)"},
+ {0x60, "Flow Control Off Command (FCoff)"},
+ {0xe0, "Modem Status Command (MSC)"},
+ {0x10, "Non Supported Command Response (NSC)"},
+ {0x90, "Remote Port Negotiation Command (RPN)"},
+ {0x50, "Remote Line Status Command (RLS)"},
+ {0x40, "Power Saving Control (PSC)"},
+ {0xc0, "Multiplexer close down (CLD)"},
+ {0xd0, "Service Negotiation Command (SNC)"},
+#endif
+ {0x0, NULL}
};
static const value_string vs_ea[] = {
- {1, "Last field octet"},
- {0, "More field octets following"},
- {0, NULL}
+ {1, "Last field octet"},
+ {0, "More field octets following"},
+ {0, NULL}
};
static const value_string vs_cr[] = {
- {1, "Command"},
- {0, "Response"},
- {0, NULL}
+ {1, "Command"},
+ {0, "Response"},
+ {0, NULL}
};
static int
get_le_multi_byte_value(tvbuff_t *tvb, int offset, proto_tree *tree, guint32 *val_ptr, int hf_index)
{
- guint8 byte, bc = 0;
- guint32 val = 0;
- int start_offset=offset;
+ guint8 byte, bc = 0;
+ guint32 val = 0;
+ int start_offset = offset;
- do{
- byte = tvb_get_guint8(tvb, offset);
- offset++;
- val |= ((byte>>1)&0xff) << (bc++ * 7);
- }while((byte & 0x1)==0);
+ do {
+ byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ val |= ((byte>>1)&0xff) << (bc++ * 7);
+ } while ((byte & 0x1) == 0);
- *val_ptr = val;
+ *val_ptr = val;
- if(hf_index>0){
- proto_tree_add_uint(tree, hf_index, tvb, start_offset, offset-start_offset, val);
- }
+ if (hf_index > 0) {
+ proto_tree_add_uint(tree, hf_index, tvb, start_offset, offset-start_offset, val);
+ }
- return offset;
+ return offset;
}
static int
dissect_ctrl_pn(packet_info *pinfo, proto_tree *t, tvbuff_t *tvb, int offset, int cr_flag)
{
- proto_tree *st;
- proto_item *ti;
- int dlci;
- int cl;
- dlci_state_t *dlci_state;
- guint8 flags;
-
- /* dlci */
- dlci=tvb_get_guint8(tvb, offset)&0x3f;
- proto_tree_add_uint(t, hf_dlci, tvb, offset, 1, dlci);
- offset++;
-
- /* cl */
- flags=tvb_get_guint8(tvb, offset);
- cl=flags&0xf0;
-
- ti = proto_tree_add_text(t, tvb, offset, 1, "I1-I4: 0x%x, C1-C4: 0x%x", flags&0xf, (flags>>4)&0xf);
- st = proto_item_add_subtree(ti, ett_ctrl_pn_ci);
-
- proto_tree_add_item(st, hf_pn_c14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(st, hf_pn_i14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- /* priority */
- proto_tree_add_item(t, hf_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- /* Ack timer */
- proto_tree_add_text(t, tvb, offset, 1, "Acknowledgement timer (T1): %d ms", (guint32)tvb_get_guint8(tvb, offset) * 100);
- offset++;
-
- /* max frame size */
- proto_tree_add_item(t, hf_max_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset+=2;
-
- /* max retrans */
- proto_tree_add_item(t, hf_max_retrans, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- /* error recovery mode */
- proto_tree_add_item(t, hf_error_recovery_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- if(!pinfo->fd->flags.visited){
- guint32 token;
-
- if( pinfo->p2p_dir == cr_flag )
- token = dlci | 0x01; /* local service */
- else
- token = dlci;
-
- dlci_state=se_tree_lookup32(dlci_table, token);
- if(!dlci_state){
- dlci_state=se_alloc0(sizeof(dlci_state_t));
- se_tree_insert32(dlci_table, token, dlci_state);
- }
-
- if(!cl){
- /* sender does not do credit based flow control */
- dlci_state->do_credit_fc = 0;
- } else if(cr_flag && (cl==0xf0)){
- /* sender requests to use credit based flow control */
- dlci_state->do_credit_fc |= 1;
- } else if((!cr_flag) && (cl==0xe0)){
- /* receiver also knows how to handle credit based
- flow control */
- dlci_state->do_credit_fc |= 2;
- }
- }
- return offset;
+ proto_tree *st;
+ proto_item *ti;
+ int dlci;
+ int cl;
+ dlci_state_t *dlci_state;
+ guint8 flags;
+
+ /* dlci */
+ dlci = tvb_get_guint8(tvb, offset) & 0x3f;
+ proto_tree_add_uint(t, hf_dlci, tvb, offset, 1, dlci);
+ offset += 1;
+
+ /* cl */
+ flags = tvb_get_guint8(tvb, offset);
+ cl = flags&0xf0;
+
+ ti = proto_tree_add_text(t, tvb, offset, 1, "I1-I4: 0x%x, C1-C4: 0x%x", flags&0xf, (flags>>4)&0xf);
+ st = proto_item_add_subtree(ti, ett_ctrl_pn_ci);
+
+ proto_tree_add_item(st, hf_pn_c14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(st, hf_pn_i14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* priority */
+ proto_tree_add_item(t, hf_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* Ack timer */
+ proto_tree_add_text(t, tvb, offset, 1, "Acknowledgement timer (T1): %d ms", (guint32)tvb_get_guint8(tvb, offset) * 100);
+ offset += 1;
+
+ /* max frame size */
+ proto_tree_add_item(t, hf_max_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* max retrans */
+ proto_tree_add_item(t, hf_max_retrans, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* error recovery mode */
+ proto_tree_add_item(t, hf_error_recovery_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ if (!pinfo->fd->flags.visited) {
+ guint32 token;
+
+ if (pinfo->p2p_dir == cr_flag)
+ token = dlci | 0x01; /* local service */
+ else
+ token = dlci;
+
+ dlci_state = se_tree_lookup32(dlci_table, token);
+ if (!dlci_state) {
+ dlci_state = se_alloc0(sizeof(dlci_state_t));
+ se_tree_insert32(dlci_table, token, dlci_state);
+ }
+
+ if (!cl) {
+ /* sender does not do credit based flow control */
+ dlci_state->do_credit_fc = 0;
+ } else if (cr_flag && (cl == 0xf0)) {
+ /* sender requests to use credit based flow control */
+ dlci_state->do_credit_fc |= 1;
+ } else if ((!cr_flag) && (cl == 0xe0)) {
+ /* receiver also knows how to handle credit based
+ flow control */
+ dlci_state->do_credit_fc |= 2;
+ }
+ }
+ return offset;
}
static int
dissect_ctrl_msc(proto_tree *t, tvbuff_t *tvb, int offset, int length)
{
- proto_tree *st;
- proto_item *it;
- guint8 status;
- int start_offset;
-
- proto_tree_add_uint(t, hf_dlci, tvb, offset, 1, tvb_get_guint8(tvb, offset)&0x3f);
- offset++;
-
- start_offset=offset;
- status = tvb_get_guint8(tvb, offset);
- it = proto_tree_add_text(t, tvb, offset, 1, "V.24 Signals: FC = %d, RTC = %d, RTR = %d, IC = %d, DV = %d", (status >> 1) & 1,
- (status >> 2) & 1, (status >> 3) & 1,
- (status >> 6) & 1, (status >> 7) & 1);
- st = proto_item_add_subtree(it, ett_ctrl_pn_v24);
-
- proto_tree_add_item(st, hf_msc_fc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(st, hf_msc_rtc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(st, hf_msc_rtr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(st, hf_msc_ic, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(st, hf_msc_dv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
-
- if(length==3){
- proto_tree_add_text(t, tvb, offset, 1, "Break bits B1-B3: 0x%x", (tvb_get_guint8(tvb, offset) & 0xf) >> 1);
- proto_tree_add_item(t, hf_msc_l, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- }
-
- proto_item_set_len(it, offset-start_offset);
-
- return offset;
+ proto_tree *st;
+ proto_item *it;
+ guint8 status;
+ int start_offset;
+
+ proto_tree_add_uint(t, hf_dlci, tvb, offset, 1, tvb_get_guint8(tvb, offset)&0x3f);
+ offset += 1;
+
+ start_offset = offset;
+ status = tvb_get_guint8(tvb, offset);
+ it = proto_tree_add_text(t, tvb, offset, 1, "V.24 Signals: FC = %d, RTC = %d, RTR = %d, IC = %d, DV = %d", (status >> 1) & 1,
+ (status >> 2) & 1, (status >> 3) & 1,
+ (status >> 6) & 1, (status >> 7) & 1);
+ st = proto_item_add_subtree(it, ett_ctrl_pn_v24);
+
+ proto_tree_add_item(st, hf_msc_fc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(st, hf_msc_rtc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(st, hf_msc_rtr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(st, hf_msc_ic, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(st, hf_msc_dv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ if (length == 3) {
+ proto_tree_add_text(t, tvb, offset, 1, "Break bits B1-B3: 0x%x", (tvb_get_guint8(tvb, offset) & 0xf) >> 1);
+ proto_tree_add_item(t, hf_msc_l, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+
+ proto_item_set_len(it, offset-start_offset);
+
+ return offset;
}
static int
dissect_btrfcomm_Address(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 *ea_flagp, guint8 *cr_flagp, guint8 *dlcip)
{
- proto_item *ti;
- proto_tree *addr_tree;
- guint8 dlci, cr_flag, ea_flag, flags;
+ proto_item *ti;
+ proto_tree *addr_tree;
+ guint8 dlci, cr_flag, ea_flag, flags;
- flags=tvb_get_guint8(tvb, offset);
+ flags = tvb_get_guint8(tvb, offset);
- ea_flag=flags&0x01;
- if(ea_flagp){
- *ea_flagp=ea_flag;
- }
+ ea_flag = flags&0x01;
+ if (ea_flagp) {
+ *ea_flagp = ea_flag;
+ }
- cr_flag=(flags&0x02)?1:0;
- if(cr_flagp){
- *cr_flagp=cr_flag;
- }
+ cr_flag = (flags&0x02) ? 1 : 0;
+ if (cr_flagp) {
+ *cr_flagp = cr_flag;
+ }
- dlci=flags>>2;
- if(dlcip){
- *dlcip=dlci;
- }
+ dlci = flags>>2;
+ if (dlcip) {
+ *dlcip = dlci;
+ }
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Address: E/A flag: %d, C/R flag: %d, DLCI: 0x%02x", ea_flag, cr_flag, dlci);
- addr_tree = proto_item_add_subtree(ti, ett_addr);
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Address: E/A flag: %d, C/R flag: %d, DLCI: 0x%02x", ea_flag, cr_flag, dlci);
+ addr_tree = proto_item_add_subtree(ti, ett_addr);
- proto_tree_add_uint(addr_tree, hf_dlci, tvb, offset, 1, dlci);
- proto_tree_add_item(addr_tree, hf_cr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(addr_tree, hf_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
+ proto_tree_add_uint(addr_tree, hf_dlci, tvb, offset, 1, dlci);
+ proto_tree_add_item(addr_tree, hf_cr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(addr_tree, hf_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
- return offset;
+ return offset;
}
static int
dissect_btrfcomm_Control(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 *pf_flagp, guint8 *frame_typep)
{
- proto_item *ti;
- proto_tree *hctl_tree;
- guint8 frame_type, pf_flag, flags;
+ proto_item *ti;
+ proto_tree *hctl_tree;
+ guint8 frame_type, pf_flag, flags;
- flags=tvb_get_guint8(tvb, offset);
+ flags = tvb_get_guint8(tvb, offset);
- pf_flag=(flags&0x10)?1:0;
- if(pf_flagp){
- *pf_flagp=pf_flag;
- }
+ pf_flag = (flags&0x10) ? 1 : 0;
+ if (pf_flagp) {
+ *pf_flagp = pf_flag;
+ }
- frame_type=flags&0xef;
- if(frame_typep){
- *frame_typep=frame_type;
- }
+ frame_type = flags&0xef;
+ if (frame_typep) {
+ *frame_typep = frame_type;
+ }
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Control: Frame type: %s (0x%x), P/F flag: %d", val_to_str(frame_type, vs_frame_type, "Unknown"), frame_type, pf_flag);
- hctl_tree = proto_item_add_subtree(ti, ett_control);
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Control: Frame type: %s (0x%x), P/F flag: %d",
+ val_to_str_const(frame_type, vs_frame_type, "Unknown"), frame_type, pf_flag);
+ hctl_tree = proto_item_add_subtree(ti, ett_control);
- proto_tree_add_item(hctl_tree, hf_pf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(hctl_tree, hf_frame_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(hctl_tree, hf_pf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(hctl_tree, hf_frame_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- return offset;
+ offset += 1;
+ return offset;
}
@@ -420,71 +421,74 @@ dissect_btrfcomm_Control(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 *pf
static int
dissect_btrfcomm_PayloadLen(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 *frame_lenp)
{
- guint16 frame_len;
- int start_offset=offset;
+ guint16 frame_len;
+ int start_offset = offset;
- frame_len = tvb_get_guint8(tvb, offset);
- offset++;
+ frame_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
- if(frame_len&0x01){
- frame_len >>= 1; /* 0 - 127 */
- } else {
- frame_len >>= 1; /* 128 - ... */
- frame_len |= (tvb_get_guint8(tvb, offset)) << 7;
- offset++;
- }
+ if (frame_len&0x01) {
+ frame_len >>= 1; /* 0 - 127 */
+ } else {
+ frame_len >>= 1; /* 128 - ... */
+ frame_len |= (tvb_get_guint8(tvb, offset)) << 7;
+ offset += 1;
+ }
- proto_tree_add_uint(tree, hf_len, tvb, start_offset, offset-start_offset, frame_len);
+ proto_tree_add_uint(tree, hf_len, tvb, start_offset, offset-start_offset, frame_len);
- if(frame_lenp){
- *frame_lenp=frame_len;
- }
+ if (frame_lenp) {
+ *frame_lenp = frame_len;
+ }
- return offset;
+ return offset;
}
static int
dissect_btrfcomm_MccType(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, guint8 *mcc_cr_flagp, guint8 *mcc_ea_flagp, guint32 *mcc_typep)
{
- int start_offset=offset;
- proto_item *ti;
- proto_tree *mcc_tree;
- guint8 flags, mcc_cr_flag, mcc_ea_flag;
- guint32 mcc_type;
+ int start_offset = offset;
+ proto_item *ti;
+ proto_tree *mcc_tree;
+ guint8 flags, mcc_cr_flag, mcc_ea_flag;
+ guint32 mcc_type;
- flags=tvb_get_guint8(tvb, offset);
+ flags = tvb_get_guint8(tvb, offset);
- mcc_cr_flag=(flags&0x2)?1:0;
- if(mcc_cr_flagp){
- *mcc_cr_flagp=mcc_cr_flag;
- }
+ mcc_cr_flag = (flags&0x2) ? 1 : 0;
+ if (mcc_cr_flagp) {
+ *mcc_cr_flagp = mcc_cr_flag;
+ }
- mcc_ea_flag=flags&0x1;
- if(mcc_ea_flagp){
- *mcc_ea_flagp=mcc_ea_flag;
- }
+ mcc_ea_flag = flags & 0x1;
+ if (mcc_ea_flagp) {
+ *mcc_ea_flagp = mcc_ea_flag;
+ }
- offset = get_le_multi_byte_value(tvb, offset, tree, &mcc_type, -1);
- mcc_type =(mcc_type>>1)&0x3f; /* shift c/r flag off */
- if(mcc_typep){
- *mcc_typep=mcc_type;
- }
+ offset = get_le_multi_byte_value(tvb, offset, tree, &mcc_type, -1);
+ mcc_type = (mcc_type>>1) & 0x3f; /* shift c/r flag off */
+ if (mcc_typep) {
+ *mcc_typep = mcc_type;
+ }
- if(mcc_type){
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(mcc_type, vs_ctl, "Unknown"));
- }
+ if (mcc_type) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(mcc_type, vs_ctl, "Unknown"));
+ }
- ti = proto_tree_add_text(tree, tvb, start_offset, offset-start_offset, "Type: %s (0x%x), C/R flag = %d, E/A flag = %d", val_to_str(mcc_type, vs_ctl, "Unknown"), mcc_type, mcc_cr_flag, mcc_ea_flag);
- mcc_tree = proto_item_add_subtree(ti, ett_mcc);
+ ti = proto_tree_add_text(tree, tvb, start_offset, offset-start_offset,
+ "Type: %s (0x%x), C/R flag = %d, E/A flag = %d",
+ val_to_str_const(mcc_type, vs_ctl, "Unknown"),
+ mcc_type, mcc_cr_flag, mcc_ea_flag);
+ mcc_tree = proto_item_add_subtree(ti, ett_mcc);
- proto_tree_add_item(mcc_tree, hf_mcc_cmd, tvb, start_offset, offset-start_offset, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(mcc_tree, hf_mcc_cr, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
- proto_tree_add_item(mcc_tree, hf_mcc_ea, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(mcc_tree, hf_mcc_cmd, tvb, start_offset, offset-start_offset, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(mcc_tree, hf_mcc_cr, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(mcc_tree, hf_mcc_ea, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
- return offset;
+ return offset;
}
/* This dissector is only called from L2CAP.
@@ -495,532 +499,537 @@ dissect_btrfcomm_MccType(tvbuff_t *tvb, int offset, proto_tree *tree, packet_inf
static void
dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *rfcomm_tree;
- proto_tree *ctrl_tree;
- int offset=0;
- int fcs_offset;
- guint8 dlci, cr_flag, ea_flag;
- guint8 frame_type, pf_flag;
- guint16 frame_len;
- dlci_state_t *dlci_state = NULL;
-
- ti = proto_tree_add_item(tree, proto_btrfcomm, tvb, offset, -1, ENC_NA);
- rfcomm_tree = proto_item_add_subtree(ti, ett_btrfcomm);
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFCOMM");
- switch (pinfo->p2p_dir) {
-
- case P2P_DIR_SENT:
- col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
- break;
-
- case P2P_DIR_RECV:
- col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
- break;
-
- case P2P_DIR_UNKNOWN:
- col_clear(pinfo->cinfo, COL_INFO);
- break;
-
- default:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
- pinfo->p2p_dir);
- break;
- }
-
-
- /* flags and dlci */
- offset=dissect_btrfcomm_Address(tvb, offset, rfcomm_tree, &ea_flag, &cr_flag, &dlci);
- /* pf and frame type */
- offset=dissect_btrfcomm_Control(tvb, offset, rfcomm_tree, &pf_flag, &frame_type);
- /* payload length */
- offset=dissect_btrfcomm_PayloadLen(tvb, offset, rfcomm_tree, &frame_len);
-
- if (dlci && (frame_len || (frame_type == 0xef) || (frame_type == 0x2f) )) {
- guint32 token;
-
- if( pinfo->p2p_dir == cr_flag )
- token = dlci | 0x01; /* local service */
- else
- token = dlci;
-
- dlci_state=se_tree_lookup32(dlci_table, token);
- if(!dlci_state){
- dlci_state=se_alloc0(sizeof(dlci_state_t));
- se_tree_insert32(dlci_table, token, dlci_state);
- }
- }
-
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s DLCI=%d ", val_to_str(frame_type, vs_frame_type_short, "Unknown"), dlci);
- if(dlci && (frame_type == 0x2f))
- col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", val_to_str(dlci_state->service, vs_service_classes, "Unknown"));
-
- /* UID frame */
- if(frame_type==0xef && dlci && pf_flag) {
- col_append_str(pinfo->cinfo, COL_INFO, "UID ");
- if((dlci_state->do_credit_fc&0x03)==0x03){
-/*QQQ use tvb_length_remaining()==2 and !frame_len as heuristics to catch this as well? */
- /* add credit based flow control byte */
- proto_tree_add_item(rfcomm_tree, hf_fc_credits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- offset++;
- }
- }
-
-
- fcs_offset = offset + frame_len;
-
-
- /* multiplexer control command */
- if((!dlci)&&frame_len){
- proto_item *mcc_ti;
- guint32 mcc_type, length;
- guint8 mcc_cr_flag, mcc_ea_flag;
- int start_offset=offset;
-
- col_append_str(pinfo->cinfo, COL_INFO, "MPX_CTRL ");
-
- mcc_ti = proto_tree_add_text(rfcomm_tree, tvb, offset, 1, "Multiplexer Control Command");
- ctrl_tree = proto_item_add_subtree(mcc_ti, ett_btrfcomm_ctrl);
-
- /* mcc type */
- offset=dissect_btrfcomm_MccType(tvb, offset, ctrl_tree, pinfo, &mcc_cr_flag, &mcc_ea_flag, &mcc_type);
-
- /* len */
- offset = get_le_multi_byte_value(tvb, offset, ctrl_tree, &length, hf_mcc_len);
-
-
- if (length > (guint32) tvb_length_remaining(tvb, offset)) {
- expert_add_info_format(pinfo, ctrl_tree, PI_MALFORMED, PI_ERROR, "Huge MCC length: %u", length);
- return;
- }
-
- switch(mcc_type) {
- case 0x20: /* Parameter Negotiation */
- col_append_str(pinfo->cinfo, COL_INFO, "Parameter Negotiation ");
- dissect_ctrl_pn(pinfo, ctrl_tree, tvb, offset, mcc_cr_flag);
- break;
- case 0x38: /* Model Status Command */
- col_append_str(pinfo->cinfo, COL_INFO, "Model Status Command ");
- dissect_ctrl_msc(ctrl_tree, tvb, offset, length);
- break;
- }
- offset += length;
-
- proto_item_set_len(mcc_ti, offset-start_offset);
- }
-
-
- /* try to find a higher layer dissector that has registered to handle data
- * for this kind of service, if none is found dissect it as raw "data"
- */
- if(dlci&&frame_len){
- tvbuff_t *next_tvb;
- btl2cap_data_t *l2cap_data;
- btrfcomm_data_t rfcomm_data;
-
- next_tvb = tvb_new_subset(tvb, offset, frame_len, frame_len);
-
- l2cap_data = pinfo->private_data;
- pinfo->private_data = &rfcomm_data;
- rfcomm_data.chandle = l2cap_data->chandle;
- rfcomm_data.cid = l2cap_data->cid;
- rfcomm_data.dlci = dlci;
-
- if(!dissector_try_uint(rfcomm_service_dissector_table, dlci_state->service,
- next_tvb, pinfo, tree)){
- /* unknown service, let the data dissector handle it */
- call_dissector(data_handle, next_tvb, pinfo, tree);
- }
- }
-
- proto_tree_add_item(rfcomm_tree, hf_fcs, tvb, fcs_offset, 1, ENC_LITTLE_ENDIAN);
+ proto_item *ti;
+ proto_tree *rfcomm_tree;
+ proto_tree *ctrl_tree;
+ int offset = 0;
+ int fcs_offset;
+ guint8 dlci, cr_flag, ea_flag;
+ guint8 frame_type, pf_flag;
+ guint16 frame_len;
+ dlci_state_t *dlci_state = NULL;
+
+ ti = proto_tree_add_item(tree, proto_btrfcomm, tvb, offset, -1, ENC_NA);
+ rfcomm_tree = proto_item_add_subtree(ti, ett_btrfcomm);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFCOMM");
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
+ break;
+
+ case P2P_DIR_RECV:
+ col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
+ break;
+
+ case P2P_DIR_UNKNOWN:
+ col_clear(pinfo->cinfo, COL_INFO);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
+ pinfo->p2p_dir);
+ break;
+ }
+
+
+ /* flags and dlci */
+ offset = dissect_btrfcomm_Address(tvb, offset, rfcomm_tree, &ea_flag, &cr_flag, &dlci);
+ /* pf and frame type */
+ offset = dissect_btrfcomm_Control(tvb, offset, rfcomm_tree, &pf_flag, &frame_type);
+ /* payload length */
+ offset = dissect_btrfcomm_PayloadLen(tvb, offset, rfcomm_tree, &frame_len);
+
+ if (dlci && (frame_len || (frame_type == 0xef) || (frame_type == 0x2f))) {
+ guint32 token;
+
+ if (pinfo->p2p_dir == cr_flag)
+ token = dlci | 0x01; /* local service */
+ else
+ token = dlci;
+
+ dlci_state = se_tree_lookup32(dlci_table, token);
+ if (!dlci_state) {
+ dlci_state = se_alloc0(sizeof(dlci_state_t));
+ se_tree_insert32(dlci_table, token, dlci_state);
+ }
+ }
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s DLCI=%d ",
+ val_to_str_const(frame_type, vs_frame_type_short, "Unknown"), dlci);
+ if (dlci && (frame_type == 0x2f))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
+ val_to_str_ext_const(dlci_state->service, &vs_service_classes_ext, "Unknown"));
+
+ /* UID frame */
+ if ((frame_type == 0xef) && dlci && pf_flag) {
+ col_append_str(pinfo->cinfo, COL_INFO, "UID ");
+ if ((dlci_state->do_credit_fc & 0x03) == 0x03) {
+/*QQQ use tvb_length_remaining() == 2 and !frame_len as heuristics to catch this as well? */
+ /* add credit based flow control byte */
+ proto_tree_add_item(rfcomm_tree, hf_fc_credits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ }
+ }
+
+
+ fcs_offset = offset + frame_len;
+
+
+ /* multiplexer control command */
+ if (!dlci && frame_len) {
+ proto_item *mcc_ti;
+ guint32 mcc_type, length;
+ guint8 mcc_cr_flag, mcc_ea_flag;
+ int start_offset = offset;
+
+ col_append_str(pinfo->cinfo, COL_INFO, "MPX_CTRL ");
+
+ mcc_ti = proto_tree_add_text(rfcomm_tree, tvb, offset, 1, "Multiplexer Control Command");
+ ctrl_tree = proto_item_add_subtree(mcc_ti, ett_btrfcomm_ctrl);
+
+ /* mcc type */
+ offset = dissect_btrfcomm_MccType(tvb, offset, ctrl_tree, pinfo, &mcc_cr_flag, &mcc_ea_flag, &mcc_type);
+
+ /* len */
+ offset = get_le_multi_byte_value(tvb, offset, ctrl_tree, &length, hf_mcc_len);
+
+
+ if (length > (guint32) tvb_length_remaining(tvb, offset)) {
+ expert_add_info_format(pinfo, ctrl_tree, PI_MALFORMED, PI_ERROR, "Huge MCC length: %u", length);
+ return;
+ }
+
+ switch(mcc_type) {
+ case 0x20: /* Parameter Negotiation */
+ col_append_str(pinfo->cinfo, COL_INFO, "Parameter Negotiation ");
+ dissect_ctrl_pn(pinfo, ctrl_tree, tvb, offset, mcc_cr_flag);
+ break;
+ case 0x38: /* Model Status Command */
+ col_append_str(pinfo->cinfo, COL_INFO, "Model Status Command ");
+ dissect_ctrl_msc(ctrl_tree, tvb, offset, length);
+ break;
+ }
+ offset += length;
+
+ proto_item_set_len(mcc_ti, offset-start_offset);
+ }
+
+
+ /* try to find a higher layer dissector that has registered to handle data
+ * for this kind of service, if none is found dissect it as raw "data"
+ */
+ if (dlci && frame_len) {
+ tvbuff_t *next_tvb;
+ btl2cap_data_t *l2cap_data;
+ btrfcomm_data_t rfcomm_data;
+
+ next_tvb = tvb_new_subset(tvb, offset, frame_len, frame_len);
+
+ l2cap_data = pinfo->private_data;
+ pinfo->private_data = &rfcomm_data;
+ rfcomm_data.chandle = l2cap_data->chandle;
+ rfcomm_data.cid = l2cap_data->cid;
+ rfcomm_data.dlci = dlci;
+
+ if (!dissector_try_uint(rfcomm_service_dissector_table, dlci_state->service,
+ next_tvb, pinfo, tree)) {
+ /* unknown service, let the data dissector handle it */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+
+ proto_tree_add_item(rfcomm_tree, hf_fcs, tvb, fcs_offset, 1, ENC_LITTLE_ENDIAN);
}
void
proto_register_btrfcomm(void)
{
- static hf_register_info hf[] = {
- {&hf_dlci,
- {"DLCI", "btrfcomm.dlci",
- FT_UINT8, BASE_HEX, NULL, 0,
- "RFCOMM DLCI", HFILL}
- },
- {&hf_priority,
- {"Priority", "btrfcomm.priority",
- FT_UINT8, BASE_DEC, NULL, 0x3f,
- NULL, HFILL}
- },
- {&hf_max_frame_size,
- {"Max Frame Size", "btrfcomm.max_frame_size",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Maximum Frame Size", HFILL}
- },
- {&hf_max_retrans,
- {"Max Retrans", "btrfcomm.max_retrans",
- FT_UINT8, BASE_DEC, NULL, 0,
- "Maximum number of retransmissions", HFILL}
- },
- {&hf_error_recovery_mode,
- {"Error Recovery Mode", "btrfcomm.error_recovery_mode",
- FT_UINT8, BASE_DEC, NULL, 0x07,
- NULL, HFILL}
- },
- {&hf_ea,
- {"EA Flag", "btrfcomm.ea",
- FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1,
- "EA flag (should be always 1)", HFILL}
- },
- {&hf_cr,
- {"C/R Flag", "btrfcomm.cr",
- FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2,
- "Command/Response flag", HFILL}
- },
- {&hf_mcc_ea,
- {"EA Flag", "btrfcomm.mcc.ea",
- FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1,
- "EA flag (should be always 1)", HFILL}
- },
- {&hf_mcc_cr,
- {"C/R Flag", "btrfcomm.mcc.cr",
- FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2,
- "Command/Response flag", HFILL}
- },
- {&hf_mcc_cmd,
- {"C/R Flag", "btrfcomm.mcc.cmd",
- FT_UINT8, BASE_HEX, VALS(vs_ctl), 0xfc,
- "Command/Response flag", HFILL}
- },
- {&hf_frame_type,
- {"Frame type", "btrfcomm.frame_type",
- FT_UINT8, BASE_HEX, VALS(vs_frame_type), 0xef,
- "Command/Response flag", HFILL}
- },
- {&hf_pf,
- {"P/F flag", "btrfcomm.pf",
- FT_UINT8, BASE_HEX, NULL, 0x10,
- "Poll/Final bit", HFILL}
- },
- {&hf_pn_i14,
- {"Type of frame", "btrfcomm.pn.i",
- FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_i), 0x0f,
- "Type of information frames used for that particular DLCI",
- HFILL}
- },
- {&hf_pn_c14,
- {"Convergence layer", "btrfcomm.pn.cl",
- FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_cl), 0xf0,
- "Convergence layer used for that particular DLCI", HFILL}
- },
- {&hf_len,
- {"Payload length", "btrfcomm.len",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Frame length", HFILL}
- },
- {&hf_mcc_len,
- {"MCC Length", "btrfcomm.mcc.len",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Length of MCC data", HFILL}
- },
- {&hf_fcs,
- {"Frame Check Sequence", "btrfcomm.fcs",
- FT_UINT8, BASE_HEX, NULL, 0,
- "Checksum over frame", HFILL}
- },
- {&hf_msc_fc,
- {"Flow Control (FC)", "btrfcomm.msc.fc",
- FT_UINT8, BASE_HEX, NULL, 0x2,
- "Flow Control", HFILL}
- },
- {&hf_msc_rtc,
- {"Ready To Communicate (RTC)", "btrfcomm.msc.rtc",
- FT_UINT8, BASE_HEX, NULL, 0x4,
- "Ready To Communicate", HFILL}
- },
- {&hf_msc_rtr,
- {"Ready To Receive (RTR)", "btrfcomm.msc.rtr",
- FT_UINT8, BASE_HEX, NULL, 0x8,
- "Ready To Receive", HFILL}
- },
- {&hf_msc_ic,
- {"Incoming Call Indicator (IC)", "btrfcomm.msc.ic",
- FT_UINT8, BASE_HEX, NULL, 0x40,
- "Incoming Call Indicator", HFILL}
- },
- {&hf_msc_dv,
- {"Data Valid (DV)", "btrfcomm.msc.dv",
- FT_UINT8, BASE_HEX, NULL, 0x80,
- "Data Valid", HFILL}
- },
- {&hf_msc_l,
- {"Length of break in units of 200ms", "btrfcomm.msc.bl",
- FT_UINT8, BASE_DEC, NULL, 0xf0,
- NULL, HFILL}
- },
- {&hf_fc_credits,
- {"Credits", "btrfcomm.credits",
- FT_UINT8, BASE_DEC, NULL, 0,
- "Flow control: number of UIH frames allowed to send", HFILL}
- }
-
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btrfcomm,
- &ett_btrfcomm_ctrl,
- &ett_addr,
- &ett_control,
- &ett_mcc,
- &ett_ctrl_pn_ci,
- &ett_ctrl_pn_v24
- };
-
- /* Register the protocol name and description */
- proto_btrfcomm = proto_register_protocol("Bluetooth RFCOMM Protocol", "RFCOMM", "btrfcomm");
-
- register_dissector("btrfcomm", dissect_btrfcomm, proto_btrfcomm);
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_btrfcomm, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- rfcomm_service_dissector_table = register_dissector_table("btrfcomm.service", "RFCOMM SERVICE", FT_UINT16, BASE_HEX);
-
- dlci_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "RFCOMM dlci table");
+ static hf_register_info hf[] = {
+ { &hf_dlci,
+ { "DLCI", "btrfcomm.dlci",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "RFCOMM DLCI", HFILL}
+ },
+ { &hf_priority,
+ { "Priority", "btrfcomm.priority",
+ FT_UINT8, BASE_DEC, NULL, 0x3f,
+ NULL, HFILL}
+ },
+ { &hf_max_frame_size,
+ { "Max Frame Size", "btrfcomm.max_frame_size",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Maximum Frame Size", HFILL}
+ },
+ { &hf_max_retrans,
+ { "Max Retrans", "btrfcomm.max_retrans",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Maximum number of retransmissions", HFILL}
+ },
+ { &hf_error_recovery_mode,
+ { "Error Recovery Mode", "btrfcomm.error_recovery_mode",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ NULL, HFILL}
+ },
+ { &hf_ea,
+ { "EA Flag", "btrfcomm.ea",
+ FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1,
+ "EA flag (should be always 1)", HFILL}
+ },
+ { &hf_cr,
+ { "C/R Flag", "btrfcomm.cr",
+ FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2,
+ "Command/Response flag", HFILL}
+ },
+ { &hf_mcc_ea,
+ { "EA Flag", "btrfcomm.mcc.ea",
+ FT_UINT8, BASE_HEX, VALS(vs_ea), 0x1,
+ "EA flag (should be always 1)", HFILL}
+ },
+ { &hf_mcc_cr,
+ { "C/R Flag", "btrfcomm.mcc.cr",
+ FT_UINT8, BASE_HEX, VALS(vs_cr), 0x2,
+ "Command/Response flag", HFILL}
+ },
+ { &hf_mcc_cmd,
+ { "C/R Flag", "btrfcomm.mcc.cmd",
+ FT_UINT8, BASE_HEX, VALS(vs_ctl), 0xfc,
+ "Command/Response flag", HFILL}
+ },
+ { &hf_frame_type,
+ { "Frame type", "btrfcomm.frame_type",
+ FT_UINT8, BASE_HEX, VALS(vs_frame_type), 0xef,
+ "Command/Response flag", HFILL}
+ },
+ { &hf_pf,
+ { "P/F flag", "btrfcomm.pf",
+ FT_UINT8, BASE_HEX, NULL, 0x10,
+ "Poll/Final bit", HFILL}
+ },
+ { &hf_pn_i14,
+ { "Type of frame", "btrfcomm.pn.i",
+ FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_i), 0x0f,
+ "Type of information frames used for that particular DLCI",
+ HFILL}
+ },
+ { &hf_pn_c14,
+ { "Convergence layer", "btrfcomm.pn.cl",
+ FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_cl), 0xf0,
+ "Convergence layer used for that particular DLCI", HFILL}
+ },
+ { &hf_len,
+ { "Payload length", "btrfcomm.len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Frame length", HFILL}
+ },
+ { &hf_mcc_len,
+ { "MCC Length", "btrfcomm.mcc.len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Length of MCC data", HFILL}
+ },
+ { &hf_fcs,
+ { "Frame Check Sequence", "btrfcomm.fcs",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Checksum over frame", HFILL}
+ },
+ { &hf_msc_fc,
+ { "Flow Control (FC)", "btrfcomm.msc.fc",
+ FT_UINT8, BASE_HEX, NULL, 0x2,
+ "Flow Control", HFILL}
+ },
+ { &hf_msc_rtc,
+ { "Ready To Communicate (RTC)", "btrfcomm.msc.rtc",
+ FT_UINT8, BASE_HEX, NULL, 0x4,
+ "Ready To Communicate", HFILL}
+ },
+ { &hf_msc_rtr,
+ { "Ready To Receive (RTR)", "btrfcomm.msc.rtr",
+ FT_UINT8, BASE_HEX, NULL, 0x8,
+ "Ready To Receive", HFILL}
+ },
+ { &hf_msc_ic,
+ { "Incoming Call Indicator (IC)", "btrfcomm.msc.ic",
+ FT_UINT8, BASE_HEX, NULL, 0x40,
+ "Incoming Call Indicator", HFILL}
+ },
+ { &hf_msc_dv,
+ { "Data Valid (DV)", "btrfcomm.msc.dv",
+ FT_UINT8, BASE_HEX, NULL, 0x80,
+ "Data Valid", HFILL}
+ },
+ { &hf_msc_l,
+ { "Length of break in units of 200ms", "btrfcomm.msc.bl",
+ FT_UINT8, BASE_DEC, NULL, 0xf0,
+ NULL, HFILL}
+ },
+ { &hf_fc_credits,
+ { "Credits", "btrfcomm.credits",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Flow control: number of UIH frames allowed to send", HFILL}
+ }
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btrfcomm,
+ &ett_btrfcomm_ctrl,
+ &ett_addr,
+ &ett_control,
+ &ett_mcc,
+ &ett_ctrl_pn_ci,
+ &ett_ctrl_pn_v24
+ };
+
+ /* Register the protocol name and description */
+ proto_btrfcomm = proto_register_protocol("Bluetooth RFCOMM Protocol", "RFCOMM", "btrfcomm");
+
+ register_dissector("btrfcomm", dissect_btrfcomm, proto_btrfcomm);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btrfcomm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ rfcomm_service_dissector_table = register_dissector_table("btrfcomm.service", "RFCOMM SERVICE", FT_UINT16, BASE_HEX);
+
+ dlci_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "RFCOMM dlci table");
}
static int
btrfcomm_sdp_tap_packet(void *arg _U_, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *arg2)
{
- btsdp_data_t *sdp_data = (btsdp_data_t *) arg2;
-
- if( sdp_data->protocol == BTSDP_RFCOMM_PROTOCOL_UUID ) {
- guint32 token;
- dlci_state_t *dlci_state;
-
- /* rfcomm channel * 2 = dlci */
- token = (sdp_data->channel<<1) | (sdp_data->flags & BTSDP_LOCAL_SERVICE_FLAG_MASK);
-
- dlci_state=se_tree_lookup32(dlci_table, token);
- if(!dlci_state){
- dlci_state=se_alloc0(sizeof(dlci_state_t));
- se_tree_insert32(dlci_table, token, dlci_state);
- }
- dlci_state->service = sdp_data->service;
- }
- return 0;
+ btsdp_data_t *sdp_data = (btsdp_data_t *) arg2;
+
+ if (sdp_data->protocol == BTSDP_RFCOMM_PROTOCOL_UUID) {
+ guint32 token;
+ dlci_state_t *dlci_state;
+
+ /* rfcomm channel * 2 = dlci */
+ token = (sdp_data->channel<<1) | (sdp_data->flags & BTSDP_LOCAL_SERVICE_FLAG_MASK);
+
+ dlci_state = se_tree_lookup32(dlci_table, token);
+ if (!dlci_state) {
+ dlci_state = se_alloc0(sizeof(dlci_state_t));
+ se_tree_insert32(dlci_table, token, dlci_state);
+ }
+ dlci_state->service = sdp_data->service;
+ }
+ return 0;
}
void
proto_reg_handoff_btrfcomm(void)
{
- dissector_handle_t btrfcomm_handle;
+ dissector_handle_t btrfcomm_handle;
- btrfcomm_handle = find_dissector("btrfcomm");
- dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM, btrfcomm_handle);
+ btrfcomm_handle = find_dissector("btrfcomm");
+ dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM, btrfcomm_handle);
- data_handle = find_dissector("data");
+ data_handle = find_dissector("data");
- /* tap into the btsdp dissector to look for rfcomm channel infomation that
- helps us determine the type of rfcomm payload, i.e. which service is
- using the channels so we know which sub-dissector to call */
- register_tap_listener("btsdp", NULL, NULL, TL_IS_DISSECTOR_HELPER, NULL, btrfcomm_sdp_tap_packet, NULL);
+ /* tap into the btsdp dissector to look for rfcomm channel infomation that
+ helps us determine the type of rfcomm payload, i.e. which service is
+ using the channels so we know which sub-dissector to call */
+ register_tap_listener("btsdp", NULL, NULL, TL_IS_DISSECTOR_HELPER, NULL, btrfcomm_sdp_tap_packet, NULL);
}
/* Bluetooth Handsfree (HF) profile dissection */
static void
dissect_bthf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
+ proto_item *ti;
+ proto_tree *st;
- guint length = tvb_length(tvb);
+ guint length = tvb_length(tvb);
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "HANDSFREE");
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HANDSFREE");
- ti = proto_tree_add_item(tree, proto_bthf, tvb, 0, -1, ENC_NA);
- st = proto_item_add_subtree(ti, ett_bthf);
+ ti = proto_tree_add_item(tree, proto_bthf, tvb, 0, -1, ENC_NA);
+ st = proto_item_add_subtree(ti, ett_bthf);
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd", tvb_format_text(tvb, 0, length));
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
+ (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
+ tvb_format_text(tvb, 0, length));
- proto_tree_add_item(st, hf_at_cmd, tvb, 0, -1, ENC_ASCII|ENC_NA);
+ proto_tree_add_item(st, hf_at_cmd, tvb, 0, -1, ENC_ASCII|ENC_NA);
}
void
proto_register_bthf(void)
{
- static hf_register_info hf[] = {
- {&hf_at_cmd,
- {"AT Cmd", "bthf.atcmd",
- FT_STRING, BASE_NONE, NULL, 0,
- "AT Command", HFILL}
- },
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_bthf,
- };
-
- proto_bthf = proto_register_protocol("Bluetooth Handsfree Packet", "BTHF", "bthf");
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_bthf, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
+ static hf_register_info hf[] = {
+ { &hf_at_cmd,
+ { "AT Cmd", "bthf.atcmd",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "AT Command", HFILL}
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_bthf,
+ };
+
+ proto_bthf = proto_register_protocol("Bluetooth Handsfree Packet", "BTHF", "bthf");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bthf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_bthf(void)
{
- dissector_handle_t bthf_handle;
+ dissector_handle_t bthf_handle;
- bthf_handle = create_dissector_handle(dissect_bthf, proto_bthf);
+ bthf_handle = create_dissector_handle(dissect_bthf, proto_bthf);
- dissector_add_uint("btrfcomm.service", BTSDP_HFP_SERVICE_UUID, bthf_handle);
- dissector_add_uint("btrfcomm.service", BTSDP_HFP_GW_SERVICE_UUID, bthf_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_HFP_SERVICE_UUID, bthf_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_HFP_GW_SERVICE_UUID, bthf_handle);
}
/* Bluetooth Dial-Up Networking (DUN) profile dissection */
static void
dissect_btdun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
- gboolean is_at_cmd;
- guint i, length;
-
- length = tvb_length(tvb);
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "DUN");
-
- ti = proto_tree_add_item(tree, proto_btdun, tvb, 0, -1, ENC_NA);
- st = proto_item_add_subtree(ti, ett_btdun);
-
- is_at_cmd = TRUE;
- for(i=0;i<length && is_at_cmd;i++) {
- is_at_cmd = tvb_get_guint8(tvb, i) < 0x7d;
- }
-
- if( is_at_cmd) {
- /* presumably an AT command */
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd", tvb_format_text(tvb, 0, length));
-
- proto_tree_add_item(st, hf_dun_at_cmd, tvb, 0, -1, ENC_ASCII|ENC_NA);
- }
- else {
- /* ... or raw PPP */
- if( ppp_handle )
- call_dissector(ppp_handle, tvb, pinfo, tree);
- else {
- /* TODO: remove the above 'if' and this 'else-body' when "ppp_raw_hdlc" is available, requires that it is
- made non-anonymous in ppp dissector to use */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s <PPP frame>", pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd");
-
- call_dissector(data_handle, tvb, pinfo, tree);
- }
- }
+ proto_item *ti;
+ proto_tree *st;
+ gboolean is_at_cmd;
+ guint i, length;
+
+ length = tvb_length(tvb);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DUN");
+
+ ti = proto_tree_add_item(tree, proto_btdun, tvb, 0, -1, ENC_NA);
+ st = proto_item_add_subtree(ti, ett_btdun);
+
+ is_at_cmd = TRUE;
+ for(i=0; i<length && is_at_cmd; i++) {
+ is_at_cmd = tvb_get_guint8(tvb, i) < 0x7d;
+ }
+
+ if (is_at_cmd) {
+ /* presumably an AT command */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
+ (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
+ tvb_format_text(tvb, 0, length));
+
+ proto_tree_add_item(st, hf_dun_at_cmd, tvb, 0, -1, ENC_ASCII|ENC_NA);
+ }
+ else {
+ /* ... or raw PPP */
+ if (ppp_handle)
+ call_dissector(ppp_handle, tvb, pinfo, tree);
+ else {
+ /* TODO: remove the above 'if' and this 'else-body' when "ppp_raw_hdlc" is available, requires that it is
+ made non-anonymous in ppp dissector to use */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s <PPP frame>", (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd");
+
+ call_dissector(data_handle, tvb, pinfo, tree);
+ }
+ }
}
void
proto_register_btdun(void)
{
- static hf_register_info hf[] = {
- {&hf_dun_at_cmd,
- {"AT Cmd", "btdun.atcmd",
- FT_STRING, BASE_NONE, NULL, 0,
- "AT Command", HFILL}
- },
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btdun,
- };
-
- proto_btdun = proto_register_protocol("Bluetooth DUN Packet", "BTDUN", "btdun");
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_bthf, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
+ static hf_register_info hf[] = {
+ { &hf_dun_at_cmd,
+ { "AT Cmd", "btdun.atcmd",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "AT Command", HFILL}
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btdun,
+ };
+
+ proto_btdun = proto_register_protocol("Bluetooth DUN Packet", "BTDUN", "btdun");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bthf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_btdun(void)
{
- dissector_handle_t btdun_handle;
+ dissector_handle_t btdun_handle;
- btdun_handle = create_dissector_handle(dissect_btdun, proto_btdun);
+ btdun_handle = create_dissector_handle(dissect_btdun, proto_btdun);
- dissector_add_uint("btrfcomm.service", BTSDP_DUN_SERVICE_UUID, btdun_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_DUN_SERVICE_UUID, btdun_handle);
- ppp_handle = find_dissector("ppp_raw_hdlc");
+ ppp_handle = find_dissector("ppp_raw_hdlc");
}
/* Bluetooth Serial Port profile (SPP) dissection */
static void
dissect_btspp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
- gboolean ascii_only;
- guint i, length = tvb_length(tvb);
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPP");
-
- ti = proto_tree_add_item(tree, proto_btspp, tvb, 0, -1, ENC_NA);
- st = proto_item_add_subtree(ti, ett_btspp);
-
- length = MIN(length,60);
- ascii_only = TRUE;
- for(i=0;i<length && ascii_only;i++) {
- ascii_only = tvb_get_guint8(tvb, i) < 0x80;
- }
-
- if(ascii_only) {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s%s\"",
- pinfo->p2p_dir==P2P_DIR_SENT?"Sent":"Rcvd",
- tvb_format_text(tvb, 0, length),
- tvb_length(tvb) > length ? "...":"");
- }
-
- proto_tree_add_item(st, hf_data, tvb, 0, -1, ENC_NA);
+ proto_item *ti;
+ proto_tree *st;
+ gboolean ascii_only;
+ guint i, length = tvb_length(tvb);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPP");
+
+ ti = proto_tree_add_item(tree, proto_btspp, tvb, 0, -1, ENC_NA);
+ st = proto_item_add_subtree(ti, ett_btspp);
+
+ length = MIN(length,60);
+ ascii_only = TRUE;
+ for(i=0; i<length && ascii_only; i++) {
+ ascii_only = tvb_get_guint8(tvb, i) < 0x80;
+ }
+
+ if (ascii_only) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s%s\"",
+ (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
+ tvb_format_text(tvb, 0, length),
+ (tvb_length(tvb) > length) ? "..." : "");
+ }
+
+ proto_tree_add_item(st, hf_data, tvb, 0, -1, ENC_NA);
}
void
proto_register_btspp(void)
{
- static hf_register_info hf[] = {
- {&hf_data,
- {"Data", "btspp.data",
- FT_BYTES, BASE_NONE, NULL, 0,
- NULL, HFILL}},
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_btspp,
- };
-
- proto_btspp = proto_register_protocol("Bluetooth SPP Packet", "BTSPP", "btspp");
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_bthf, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
+ static hf_register_info hf[] = {
+ { &hf_data,
+ { "Data", "btspp.data",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL}
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_btspp,
+ };
+
+ proto_btspp = proto_register_protocol("Bluetooth SPP Packet", "BTSPP", "btspp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bthf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_btspp(void)
{
- dissector_handle_t btspp_handle;
+ dissector_handle_t btspp_handle;
- btspp_handle = create_dissector_handle(dissect_btspp, proto_btspp);
+ btspp_handle = create_dissector_handle(dissect_btspp, proto_btspp);
- dissector_add_uint("btrfcomm.service", BTSDP_SPP_SERVICE_UUID, btspp_handle);
+ dissector_add_uint("btrfcomm.service", BTSDP_SPP_SERVICE_UUID, btspp_handle);
}
diff --git a/epan/dissectors/packet-btrfcomm.h b/epan/dissectors/packet-btrfcomm.h
index cd1f30f75c..57e9981df0 100644
--- a/epan/dissectors/packet-btrfcomm.h
+++ b/epan/dissectors/packet-btrfcomm.h
@@ -29,9 +29,9 @@
* chandle, cid, dlci and direction
*/
typedef struct _btrfcomm_data_t {
- guint16 chandle; /* only low 12 bits used */
- guint16 cid;
- guint8 dlci;
+ guint16 chandle; /* only low 12 bits used */
+ guint16 cid;
+ guint8 dlci;
} btrfcomm_data_t;
#endif
diff --git a/epan/dissectors/packet-btsdp.c b/epan/dissectors/packet-btsdp.c
index bda9f9f503..1cb5fa33c1 100644
--- a/epan/dissectors/packet-btsdp.c
+++ b/epan/dissectors/packet-btsdp.c
@@ -69,314 +69,416 @@ static int btsdp_tap = -1;
static emem_tree_t *service_table = NULL;
static const value_string vs_pduid[] = {
- {0x1, "Error Response"},
- {0x2, "Service Search Request"},
- {0x3, "Service Search Response"},
- {0x4, "Service Attribute Request"},
- {0x5, "Service Attribute Response"},
- {0x6, "Service Search Attribute Request"},
- {0x7, "Service Search Attribute Response"},
- {0, NULL}
+ {0x1, "Error Response"},
+ {0x2, "Service Search Request"},
+ {0x3, "Service Search Response"},
+ {0x4, "Service Attribute Request"},
+ {0x5, "Service Attribute Response"},
+ {0x6, "Service Search Attribute Request"},
+ {0x7, "Service Search Attribute Response"},
+ {0, NULL}
};
-#define ATTR_ID_SERVICE_CLASS_ID_LIST 0x0001
-#define ATTR_ID_PROTOCOL_DESCRIPTOR_LIST 0x0004
-#define ATTR_ID_BT_PROFILE_DESCRIPTOR_LIST 0x0009
-#define ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS 0x000d
-#define ATTR_ID_GOEP_L2CAP_PSM_GROUP_ID_IP_SUBNET 0x0200
+#define ATTR_ID_SERVICE_CLASS_ID_LIST 0x0001
+#define ATTR_ID_PROTOCOL_DESCRIPTOR_LIST 0x0004
+#define ATTR_ID_BT_PROFILE_DESCRIPTOR_LIST 0x0009
+#define ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS 0x000d
+#define ATTR_ID_GOEP_L2CAP_PSM_GROUP_ID_IP_SUBNET 0x0200
static const value_string vs_general_attribute_id[] = {
- {0x0000, "Service Record Handle"},
- {0x0001, "Service Class ID List"},
- {0x0002, "Service Record State"},
- {0x0003, "Service ID"},
- {0x0004, "Protocol Descriptor List"},
- {0x0005, "Browse Group List"},
- {0x0006, "Language Base Attribute ID List"},
- {0x0007, "Serviceinfo Time To Live"},
- {0x0008, "Service Availability"},
- {0x0009, "Bluetooth Profile Descriptor List"},
- {0x000a, "Documentation URL"},
- {0x000b, "Client Executable URL"},
- {0x000c, "Icon URL"},
- {0x000d, "Additional Protocol Descriptor Lists"},
- {0x0100, "Service Name"},
- {0x0101, "Service Description"},
- {0x0102, "Provider Name"},
- {0x0200, "GOEP L2CAP PSM/Group Id/IP Subnet"},
- {0x0201, "Service Database State"},
- {0x0300, "Service Version"},
- {0x0301, "Data Exchange Spec/Network/Supported Data Stores List"},
- {0x0302, "Remote Audio Volume Control/MCAP Supported Features"},
- {0x0303, "Supported Formats"},
- {0x0304, "Fax Class 2 Support"},
- {0x0305, "Audio Feedback Support"},
- {0x0306, "Network Address"},
- {0x0307, "WAP Gateway"},
- {0x0308, "Home Page URL"},
- {0x0309, "WAP Stack Type"},
- {0x030a, "Security Description"},
- {0x030b, "Net Access Type"},
- {0x030c, "Max Net Accessrate"},
- {0x030d, "IPv4 Subnet"},
- {0x030e, "IPv6 Subnet"},
- {0x0310, "Supported Capabilities"},
- {0x0311, "Supported Features"},
- {0x0312, "Supported Functions"},
- {0x0313, "Total Imaging Data Capacity"},
- {0x0314, "Supported Repositories"},
- {0x0315, "MAS Instance ID"},
- {0x0316, "Supported Message Types"},
- {0, NULL}
+ {0x0000, "Service Record Handle"},
+ {0x0001, "Service Class ID List"},
+ {0x0002, "Service Record State"},
+ {0x0003, "Service ID"},
+ {0x0004, "Protocol Descriptor List"},
+ {0x0005, "Browse Group List"},
+ {0x0006, "Language Base Attribute ID List"},
+ {0x0007, "Serviceinfo Time To Live"},
+ {0x0008, "Service Availability"},
+ {0x0009, "Bluetooth Profile Descriptor List"},
+ {0x000a, "Documentation URL"},
+ {0x000b, "Client Executable URL"},
+ {0x000c, "Icon URL"},
+ {0x000d, "Additional Protocol Descriptor Lists"},
+ {0x0100, "Service Name"},
+ {0x0101, "Service Description"},
+ {0x0102, "Provider Name"},
+ {0x0200, "GOEP L2CAP PSM/Group Id/IP Subnet"},
+ {0x0201, "Service Database State"},
+ {0x0300, "Service Version"},
+ {0x0301, "Data Exchange Spec/Network/Supported Data Stores List"},
+ {0x0302, "Remote Audio Volume Control/MCAP Supported Features"},
+ {0x0303, "Supported Formats"},
+ {0x0304, "Fax Class 2 Support"},
+ {0x0305, "Audio Feedback Support"},
+ {0x0306, "Network Address"},
+ {0x0307, "WAP Gateway"},
+ {0x0308, "Home Page URL"},
+ {0x0309, "WAP Stack Type"},
+ {0x030a, "Security Description"},
+ {0x030b, "Net Access Type"},
+ {0x030c, "Max Net Accessrate"},
+ {0x030d, "IPv4 Subnet"},
+ {0x030e, "IPv6 Subnet"},
+ {0x0310, "Supported Capabilities"},
+ {0x0311, "Supported Features"},
+ {0x0312, "Supported Functions"},
+ {0x0313, "Total Imaging Data Capacity"},
+ {0x0314, "Supported Repositories"},
+ {0x0315, "MAS Instance ID"},
+ {0x0316, "Supported Message Types"},
+ {0, NULL}
};
+/* service UUIDs */
+static const value_string vs_service_classes[] = {
+ {0x0001, "SDP"},
+ {0x0002, "UDP"},
+ {0x0003, "RFCOMM"},
+ {0x0004, "TCP"},
+ {0x0005, "TCS-BIN"},
+ {0x0006, "TCS-AT"},
+ {0x0008, "OBEX"},
+ {0x0009, "IP"},
+ {0x000A, "FTP"},
+ {0x000C, "HTTP"},
+ {0x000E, "WSP"},
+ {0x000F, "BNEP"},
+ {0x0010, "UPNP"},
+ {0x0011, "HIDP"},
+ {0x0012, "Hardcopy Control Channel"},
+ {0x0014, "Hardcopy Data Channel"},
+ {0x0016, "Hardcopy Notification"},
+ {0x0017, "AVCTP"},
+ {0x0019, "AVDTP"},
+ {0x001B, "CMPT"},
+ {0x001D, "UDI C-Plane"},
+ {0x001E, "MCAP Control Channel"},
+ {0x001F, "MCAP Data Channel"},
+ {0x0100, "L2CAP"},
+ {0x1000, "Service Discovery Server Service Class ID"},
+ {0x1001, "Browse Group Descriptor Service Class ID"},
+ {0x1002, "Public Browse Group"},
+ {0x1101, "Serial Port"},
+ {0x1102, "LAN Access Using PPP"},
+ {0x1103, "Dialup Networking"},
+ {0x1104, "IrMC Sync"},
+ {0x1105, "OBEX Object Push"},
+ {0x1106, "OBEX File Transfer"},
+ {0x1107, "IrMC Sync Command"},
+ {0x1108, "Headset"},
+ {0x1109, "Cordless Telephony"},
+ {0x110A, "Audio Source"},
+ {0x110B, "Audio Sink"},
+ {0x110C, "A/V Remote Control Target"},
+ {0x110D, "Advanced Audio Distribution"},
+ {0x110E, "A/V Remote Control"},
+ {0x110F, "Video Conferencing"},
+ {0x1110, "Intercom"},
+ {0x1111, "Fax"},
+ {0x1112, "Headset Audio Gateway"},
+ {0x1113, "WAP"},
+ {0x1114, "WAP client"},
+ {0x1115, "PANU"},
+ {0x1116, "NAP"},
+ {0x1117, "GN"},
+ {0x1118, "Direct Printing"},
+ {0x1119, "Reference Printing"},
+ {0x111A, "Imaging"},
+ {0x111B, "Imaging Responder"},
+ {0x111C, "Imaging Automatic Archive"},
+ {0x111D, "Imaging Referenced Objects"},
+ {0x111E, "Handsfree"},
+ {0x111F, "Handsfree Audio Gateway"},
+ {0x1120, "Direct Printing Reference Objects Service"},
+ {0x1121, "Reflected UI"},
+ {0x1122, "Basic Printing"},
+ {0x1123, "Printing Status"},
+ {0x1124, "Human Interface Device Service"},
+ {0x1125, "Hardcopy Cable Replacement"},
+ {0x1126, "HCR Print"},
+ {0x1127, "HCR Scan"},
+ {0x1128, "Common ISDN Access"},
+ {0x1129, "Video Conferencing GW"},
+ {0x112A, "UDI MT"},
+ {0x112B, "UDI TA"},
+ {0x112C, "Audio/Video"},
+ {0x112D, "SIM Access"},
+ {0x112E, "Phonebook Access client"},
+ {0x112F, "Phonebook Access server"},
+ {0x1130, "Phonebook Access Profile"},
+ {0x1131, "Headset - HS"},
+ {0x1132, "Message Access Server"},
+ {0x1133, "Message Notification Server"},
+ {0x1134, "Message Access Profile"},
+ {0x1200, "PnP Information"},
+ {0x1201, "Generic Networking"},
+ {0x1202, "Generic File Transfer"},
+ {0x1203, "Generic Audio"},
+ {0x1204, "Generic Telephony"},
+ {0x1205, "UPNP_Service"},
+ {0x1206, "UPNP_IP_Service"},
+ {0x1300, "ESDP_UPNP_IP_PAN"},
+ {0x1301, "ESDP_UPNP_IP_LAP"},
+ {0x1302, "ESDP_UPNP_L2CAP"},
+ {0x1303, "Video Source"},
+ {0x1304, "Video Sink"},
+ {0x1305, "Video Distribution"},
+ {0x1400, "Health Device Profile"},
+ {0x1401, "Health Device Source"},
+ {0x1402, "Health Device Sink"},
+ {0, NULL}
+};
+value_string_ext vs_service_classes_ext = VALUE_STRING_EXT_INIT(vs_service_classes);
+
static int
get_type_length(tvbuff_t *tvb, int offset, int *length)
{
- int size = 0;
- guint8 byte0 = tvb_get_guint8(tvb, offset);
- offset++;
-
- switch (byte0 & 0x07) {
- case 0:
- size = (byte0 >> 3) == 0 ? 0 : 1;
- break;
- case 1:
- size = 2;
- break;
- case 2:
- size = 4;
- break;
- case 3:
- size = 8;
- break;
- case 4:
- size = 16;
- break;
- case 5:
- size = tvb_get_guint8(tvb, offset);
- offset++;
- break;
- case 6:
- size = tvb_get_ntohs(tvb, offset);
- offset += 2;
- break;
- case 7:
- size = tvb_get_ntohl(tvb, offset);
- offset += 4;
- break;
- }
-
- *length = size;
- return offset;
+ int size = 0;
+ guint8 byte0 = tvb_get_guint8(tvb, offset);
+
+ offset += 1;
+
+ switch (byte0 & 0x07) {
+ case 0:
+ size = (byte0 >> 3) == 0 ? 0 : 1;
+ break;
+ case 1:
+ size = 2;
+ break;
+ case 2:
+ size = 4;
+ break;
+ case 3:
+ size = 8;
+ break;
+ case 4:
+ size = 16;
+ break;
+ case 5:
+ size = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ break;
+ case 6:
+ size = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ break;
+ case 7:
+ size = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ break;
+ }
+
+ *length = size;
+ return offset;
}
static guint32
get_uint_by_size(tvbuff_t *tvb, int off, int size)
{
- switch(size) {
- case 0:
- return tvb_get_guint8(tvb, off);
- case 1:
- return tvb_get_ntohs(tvb, off);
- case 2:
- return tvb_get_ntohl(tvb, off);
- default:
- return 0xffffffff;
- }
+ switch (size) {
+ case 0:
+ return tvb_get_guint8(tvb, off);
+ case 1:
+ return tvb_get_ntohs(tvb, off);
+ case 2:
+ return tvb_get_ntohl(tvb, off);
+ default:
+ return 0xffffffff;
+ }
}
static gint32
get_int_by_size(tvbuff_t *tvb, int off, int size)
{
- switch(size) {
- case 0:
- return tvb_get_guint8(tvb, off);
- case 1:
- return tvb_get_ntohs(tvb, off);
- case 2:
- return tvb_get_ntohl(tvb, off);
- default:
- return -1;
- }
+ switch (size) {
+ case 0:
+ return tvb_get_guint8(tvb, off);
+ case 1:
+ return tvb_get_ntohs(tvb, off);
+ case 2:
+ return tvb_get_ntohl(tvb, off);
+ default:
+ return -1;
+ }
}
static int
dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- proto_item *ti;
- proto_tree *st;
- int start_offset, bytes_to_go;
- guint16 id;
- const char *att_name;
-
- start_offset=offset;
- ti = proto_tree_add_text(t, tvb, offset, 2, "Attribute ID List");
- st = proto_item_add_subtree(ti, ett_btsdp_attribute_idlist);
-
- offset = get_type_length(tvb, offset, &bytes_to_go);
- proto_item_set_len(ti, offset - start_offset + bytes_to_go);
-
- while(bytes_to_go>0){
- guint8 byte0 = tvb_get_guint8(tvb, offset);
-
- if (byte0 == 0x09) { /* 16 bit attribute id */
-
- id = tvb_get_ntohs(tvb, offset+1);
- att_name = val_to_str(id, vs_general_attribute_id, "Unknown");
- proto_tree_add_text(st, tvb, offset, 3, "%s (0x%04x)", att_name, id);
- offset+=3;
- bytes_to_go-=3;
-
- col_append_fstr(pinfo->cinfo, COL_INFO, " (%s) ", att_name);
-
- } else if (byte0 == 0x0a) { /* 32 bit attribute range */
- col_append_fstr(pinfo->cinfo, COL_INFO, " (0x%04x - 0x%04x) ",
- tvb_get_ntohs(tvb, offset + 1), tvb_get_ntohs(tvb, offset + 3));
-
- proto_tree_add_text(st, tvb, offset, 5, "0x%04x - 0x%04x",
- tvb_get_ntohs(tvb, offset + 1),
- tvb_get_ntohs(tvb, offset + 3));
- offset+=5;
- bytes_to_go-=5;
- } else {
- break;
- }
- }
- return offset - start_offset;
+ proto_item *ti;
+ proto_tree *st;
+ int start_offset, bytes_to_go;
+ guint16 id;
+ const char *att_name;
+
+ start_offset = offset;
+ ti = proto_tree_add_text(t, tvb, offset, 2, "Attribute ID List");
+ st = proto_item_add_subtree(ti, ett_btsdp_attribute_idlist);
+
+ offset = get_type_length(tvb, offset, &bytes_to_go);
+ proto_item_set_len(ti, offset - start_offset + bytes_to_go);
+
+ while (bytes_to_go > 0) {
+ guint8 byte0 = tvb_get_guint8(tvb, offset);
+
+ if (byte0 == 0x09) { /* 16 bit attribute id */
+
+ id = tvb_get_ntohs(tvb, offset+1);
+ att_name = val_to_str_const(id, vs_general_attribute_id, "Unknown");
+ proto_tree_add_text(st, tvb, offset, 3, "%s (0x%04x)", att_name, id);
+ offset += 3;
+ bytes_to_go -= 3;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s) ", att_name);
+
+ } else if (byte0 == 0x0a) { /* 32 bit attribute range */
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (0x%04x - 0x%04x) ",
+ tvb_get_ntohs(tvb, offset + 1), tvb_get_ntohs(tvb, offset + 3));
+
+ proto_tree_add_text(st, tvb, offset, 5, "0x%04x - 0x%04x",
+ tvb_get_ntohs(tvb, offset + 1),
+ tvb_get_ntohs(tvb, offset + 3));
+ offset += 5;
+ bytes_to_go -= 5;
+ } else {
+ break;
+ }
+ }
+ return offset - start_offset;
}
static int
dissect_sdp_error_response(proto_tree *t, tvbuff_t *tvb, int offset) {
- proto_tree_add_item(t, hf_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset+=2;
+ proto_tree_add_item(t, hf_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
- return offset;
+ return offset;
}
static int
get_sdp_data_element(tvbuff_t *tvb, int offset, guint16 id, guint8 *type, void **val, guint32 *service, guint32 *service_val)
{
- int size, start_offset, type_size;
- guint8 byte0;
- /* guint8 size_index; */
-
- byte0=tvb_get_guint8(tvb, offset);
- *type = (byte0>>3) & 0x1f;
- /* size_index = byte0 & 0x07; set but not used, so commented out */
-
- /* Initialize the rest of the outputs */
- *val = NULL;
- *service = 0;
- *service_val = 0;
-
- start_offset=offset;
- offset = get_type_length(tvb, offset, &size);
- type_size = offset - start_offset + size;
-
- switch (*type) {
- case 0: { /* null */
- *val = NULL;
- break;
- }
- case 1: /* unsigned integer */
- case 2: /* signed integer */
- case 3: { /* uuid */
- *val = ep_alloc(size);
-
- if (size == 1) {
- *((guint8 *) *val) = tvb_get_guint8(tvb, offset);
- }
- else if (size == 2) {
- *((guint16 *) *val) = tvb_get_ntohs(tvb, offset);
- }
- else if (size == 4) {
- *((guint32 *) *val) = tvb_get_ntohl(tvb, offset);
- }
- else if (size == 8) {
- *((guint64 *) *val) = tvb_get_ntoh64(tvb, offset);
- }
- else if (size == 16) {
- /* store the short UUID part of the 128-bit base UUID */
- *((guint32 *) *val) = tvb_get_ntohl(tvb, offset);
- }
- break;
- }
- case 8: /* fall through */
- case 4: {
- *val = tvb_bytes_to_str(tvb, offset, size);
- break;
- }
- case 5: {
- *val = ep_alloc(sizeof(type_size));
- *((guint8 *) *val) = tvb_get_guint8(tvb, offset);
- break;
- }
- case 6: /* Data Element sequence */
- case 7: /* Data Element alternative */ {
- gboolean flag = FALSE;
- int bytes_to_go = size;
- int len;
- guint32 value = 0;
-
- while(bytes_to_go > 0) {
- size = get_sdp_data_element(tvb, offset, id, type, val, service, service_val);
- if (size < 1 || *val == NULL) {
- break;
- }
-
- get_type_length(tvb, offset, &len);
- offset += size;
- bytes_to_go -= size;
-
- if( len == 1 ) {
- value = *((guint8 *) *val);
- }
- else if( len == 2 ) {
- value = *((guint16 *) *val);
- }
- else if ( len == 4 ) {
- value = *((guint32 *) *val);
- }
- else if ( len == 16 ) {
- value = *((guint32 *) *val);
- }
-
- /* pick special values of interest */
- /* protocol or additional protocol list with UUID values for L2CAP or RFCOMM */
- if ( ((id == 4) || (id == 0xd)) && (*type == 3) && ((value == 0x100) || (value == 0x0003)) ) {
- *service = value;
- flag = TRUE;
- }
- /* profile descriptor list with UUID */
- else if ( (id == 9) && (*type == 3) ) {
- *service = value;
- flag = TRUE;
- }
- /* service class id list with UUID */
- else if ( (id == 1) && (*type == 3) ) {
- *service = value;
- flag = TRUE;
- }
- /* unsigned int found after value of interest */
- else if ( (flag == TRUE) && *type == 1) {
- *service_val = value;
- flag = FALSE;
- }
- else {
- flag = FALSE;
- }
- }
- break;
- }
- }
-
- return type_size;
+ int size, start_offset, type_size;
+ guint8 byte0;
+ /* guint8 size_index; */
+
+ byte0 = tvb_get_guint8(tvb, offset);
+ *type = (byte0>>3) & 0x1f;
+ /* size_index = byte0 & 0x07; set but not used, so commented out */
+
+ /* Initialize the rest of the outputs */
+ *val = NULL;
+ *service = 0;
+ *service_val = 0;
+
+ start_offset = offset;
+ offset = get_type_length(tvb, offset, &size);
+ type_size = offset - start_offset + size;
+
+ switch (*type) {
+ case 0: { /* null */
+ *val = NULL;
+ break;
+ }
+ case 1: /* unsigned integer */
+ case 2: /* signed integer */
+ case 3: { /* uuid */
+ *val = ep_alloc(size);
+
+ if (size == 1) {
+ *((guint8 *) *val) = tvb_get_guint8(tvb, offset);
+ }
+ else if (size == 2) {
+ *((guint16 *) *val) = tvb_get_ntohs(tvb, offset);
+ }
+ else if (size == 4) {
+ *((guint32 *) *val) = tvb_get_ntohl(tvb, offset);
+ }
+ else if (size == 8) {
+ *((guint64 *) *val) = tvb_get_ntoh64(tvb, offset);
+ }
+ else if (size == 16) {
+ /* store the short UUID part of the 128-bit base UUID */
+ *((guint32 *) *val) = tvb_get_ntohl(tvb, offset);
+ }
+ break;
+ }
+ case 8: /* fall through */
+ case 4: {
+ *val = tvb_bytes_to_str(tvb, offset, size);
+ break;
+ }
+ case 5: {
+ *val = ep_alloc(sizeof(type_size));
+ *((guint8 *) *val) = tvb_get_guint8(tvb, offset);
+ break;
+ }
+ case 6: /* Data Element sequence */
+ case 7: /* Data Element alternative */ {
+ gboolean flag = FALSE;
+ int bytes_to_go = size;
+ int len;
+ guint32 value = 0;
+
+ while (bytes_to_go > 0) {
+ size = get_sdp_data_element(tvb, offset, id, type, val, service, service_val);
+ if (size < 1 || *val == NULL) {
+ break;
+ }
+
+ get_type_length(tvb, offset, &len);
+ offset += size;
+ bytes_to_go -= size;
+
+ if (len == 1) {
+ value = *((guint8 *) *val);
+ }
+ else if (len == 2) {
+ value = *((guint16 *) *val);
+ }
+ else if (len == 4) {
+ value = *((guint32 *) *val);
+ }
+ else if (len == 16) {
+ value = *((guint32 *) *val);
+ }
+
+ /* pick special values of interest */
+ /* protocol or additional protocol list with UUID values for L2CAP or RFCOMM */
+ if (((id == 4) || (id == 0xd)) && (*type == 3) && ((value == 0x100) || (value == 0x0003))) {
+ *service = value;
+ flag = TRUE;
+ }
+ /* profile descriptor list with UUID */
+ else if ((id == 9) && (*type == 3)) {
+ *service = value;
+ flag = TRUE;
+ }
+ /* service class id list with UUID */
+ else if ((id == 1) && (*type == 3)) {
+ *service = value;
+ flag = TRUE;
+ }
+ /* unsigned int found after value of interest */
+ else if ((flag == TRUE) && *type == 1) {
+ *service_val = value;
+ flag = FALSE;
+ }
+ else {
+ flag = FALSE;
+ }
+ }
+ break;
+ }
+ }
+
+ return type_size;
}
@@ -384,139 +486,139 @@ static int
dissect_sdp_type(proto_tree *t, tvbuff_t *tvb, int offset, char **attr_val)
{
#define MAX_SDP_LEN 1024
- int strpos=0, size, start_offset, type_size;
- char *str;
- guint8 byte0;
- guint8 type;
- guint8 size_index;
-
- str=ep_alloc(MAX_SDP_LEN+1);
- *attr_val=str;
- str[0]=0;
-
- byte0=tvb_get_guint8(tvb, offset);
- type=(byte0>>3)&0x1f;
- size_index=byte0&0x07;
-
- start_offset=offset;
- offset = get_type_length(tvb, offset, &size);
- type_size = offset - start_offset + size;
-
-
- switch (type) {
- case 0:
- proto_tree_add_text(t, tvb, start_offset, type_size, "Nil ");
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "Nil ");
- }
- break;
- case 1: {
- guint32 val = get_uint_by_size(tvb, offset, size_index);
- proto_tree_add_text(t, tvb, start_offset, type_size,
- "unsigned int %d ", val);
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%u ", val);
- }
- break;
- }
- case 2: {
- guint32 val = get_int_by_size(tvb, offset, size_index);
- proto_tree_add_text(t, tvb, start_offset, type_size,
- "signed int %d ", val);
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%d ", val);
- }
- break;
- }
- case 3: {
- guint32 id;
- const char *uuid_name;
- char *ptr = tvb_bytes_to_str(tvb, offset, size);
-
- if(size == 2){
- id = tvb_get_ntohs(tvb, offset);
- } else {
- id = tvb_get_ntohl(tvb, offset);
- }
- uuid_name = val_to_str(id, vs_service_classes, "Unknown service");
-
- proto_tree_add_text(t, tvb, start_offset, type_size, "%s (0x%s) ", uuid_name, ptr);
-
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, ": %s", uuid_name);
- }
- break;
- }
- case 8: /* fall through */
- case 4: {
- char *ptr = (gchar*)tvb_get_ephemeral_string(tvb, offset, size);
-
- proto_tree_add_text(t, tvb, start_offset, type_size, "%s \"%s\"",
- type == 8 ? "URL" : "String", ptr);
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", ptr);
- }
- break;
- }
- case 5: {
- guint8 var = tvb_get_guint8(tvb, offset);
-
- proto_tree_add_text(t, tvb, start_offset, type_size, "%s",
- var ? "true" : "false");
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", var?"true":"false");
- }
- break;
- }
- case 6: /* Data Element sequence */
- case 7: /* Data Element alternative */ {
- proto_tree *st;
- proto_item *ti;
- int bytes_to_go = size;
- int first = 1;
- char *substr;
-
- ti = proto_tree_add_text(t, tvb, start_offset, type_size, "%s",
- type == 6 ? "Data Element sequence" :
- "Data Element alternative");
- st = proto_item_add_subtree(ti, ett_btsdp_des);
-
- if(strpos<MAX_SDP_LEN){
- strpos+=g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "{ ");
- }
-
- while(bytes_to_go > 0){
- if(!first){
- if(strpos<MAX_SDP_LEN){
- strpos+=g_snprintf(str+strpos, MAX_SDP_LEN-strpos, ", ");
- }
- } else {
- first = 0;
- }
-
- size = dissect_sdp_type(st, tvb, offset, &substr);
- if (size < 1) {
- break;
- }
- if(strpos<MAX_SDP_LEN){
- strpos+=g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", substr);
- }
- offset += size;
- bytes_to_go -= size;
- }
-
- if(strpos<MAX_SDP_LEN){
- /* strpos+= */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "} ");
- }
- break;
- }
- }
-
- /* make sure the string is 0 terminated */
- str[MAX_SDP_LEN]=0;
-
-
- return type_size;
+ int strpos = 0, size, start_offset, type_size;
+ char *str;
+ guint8 byte0;
+ guint8 type;
+ guint8 size_index;
+
+ str = ep_alloc(MAX_SDP_LEN+1);
+ *attr_val = str;
+ str[0] = 0;
+
+ byte0 = tvb_get_guint8(tvb, offset);
+ type = (byte0>>3)&0x1f;
+ size_index = byte0&0x07;
+
+ start_offset = offset;
+ offset = get_type_length(tvb, offset, &size);
+ type_size = offset - start_offset + size;
+
+
+ switch (type) {
+ case 0:
+ proto_tree_add_text(t, tvb, start_offset, type_size, "Nil ");
+ if (strpos<MAX_SDP_LEN) {
+ /* strpos += */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "Nil ");
+ }
+ break;
+ case 1: {
+ guint32 val = get_uint_by_size(tvb, offset, size_index);
+ proto_tree_add_text(t, tvb, start_offset, type_size,
+ "unsigned int %d ", val);
+ if (strpos<MAX_SDP_LEN) {
+ /* strpos += */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%u ", val);
+ }
+ break;
+ }
+ case 2: {
+ guint32 val = get_int_by_size(tvb, offset, size_index);
+ proto_tree_add_text(t, tvb, start_offset, type_size,
+ "signed int %d ", val);
+ if (strpos<MAX_SDP_LEN) {
+ /* strpos += */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%d ", val);
+ }
+ break;
+ }
+ case 3: {
+ guint32 id;
+ const char *uuid_name;
+ char *ptr = tvb_bytes_to_str(tvb, offset, size);
+
+ if (size == 2) {
+ id = tvb_get_ntohs(tvb, offset);
+ } else {
+ id = tvb_get_ntohl(tvb, offset);
+ }
+ uuid_name = val_to_str_ext_const(id, &vs_service_classes_ext, "Unknown service");
+
+ proto_tree_add_text(t, tvb, start_offset, type_size, "%s (0x%s) ", uuid_name, ptr);
+
+ if (strpos < MAX_SDP_LEN) {
+ /* strpos += */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, ": %s", uuid_name);
+ }
+ break;
+ }
+ case 8: /* fall through */
+ case 4: {
+ char *ptr = (gchar*)tvb_get_ephemeral_string(tvb, offset, size);
+
+ proto_tree_add_text(t, tvb, start_offset, type_size, "%s \"%s\"",
+ type == 8 ? "URL" : "String", ptr);
+ if (strpos < MAX_SDP_LEN) {
+ /* strpos += */g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", ptr);
+ }
+ break;
+ }
+ case 5: {
+ guint8 var = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(t, tvb, start_offset, type_size, "%s",
+ var ? "true" : "false");
+ if (strpos < MAX_SDP_LEN) {
+ /* strpos += */g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", var?"true":"false");
+ }
+ break;
+ }
+ case 6: /* Data Element sequence */
+ case 7: /* Data Element alternative */ {
+ proto_tree *st;
+ proto_item *ti;
+ int bytes_to_go = size;
+ int first = 1;
+ char *substr;
+
+ ti = proto_tree_add_text(t, tvb, start_offset, type_size, "%s",
+ type == 6 ? "Data Element sequence" :
+ "Data Element alternative");
+ st = proto_item_add_subtree(ti, ett_btsdp_des);
+
+ if (strpos < MAX_SDP_LEN) {
+ strpos += g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "{ ");
+ }
+
+ while (bytes_to_go > 0) {
+ if (!first) {
+ if (strpos<MAX_SDP_LEN) {
+ strpos += g_snprintf(str+strpos, MAX_SDP_LEN-strpos, ", ");
+ }
+ } else {
+ first = 0;
+ }
+
+ size = dissect_sdp_type(st, tvb, offset, &substr);
+ if (size < 1) {
+ break;
+ }
+ if (strpos < MAX_SDP_LEN) {
+ strpos += g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "%s ", substr);
+ }
+ offset += size;
+ bytes_to_go -= size;
+ }
+
+ if (strpos < MAX_SDP_LEN) {
+ /* strpos += */ g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "} ");
+ }
+ break;
+ }
+ }
+
+ /* make sure the string is 0 terminated */
+ str[MAX_SDP_LEN]='\0';
+
+
+ return type_size;
}
@@ -525,116 +627,116 @@ dissect_sdp_type(proto_tree *t, tvbuff_t *tvb, int offset, char **attr_val)
static int
dissect_sdp_service_attribute(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_tree *st, *ti_sa, *ti_av;
- int size;
- const char *att_name;
- guint16 id;
- char *attr_val;
-
- id = tvb_get_ntohs(tvb, offset+1);
- att_name = val_to_str(id, vs_general_attribute_id, "Unknown");
-
- ti_sa = proto_tree_add_text(tree, tvb, offset, -1,
- "Service Attribute: id = %s (0x%x)", att_name, id);
- st = proto_item_add_subtree(ti_sa, ett_btsdp_attribute);
-
- proto_tree_add_text(st, tvb, offset, 3, "Attribute ID: %s (0x%x)", att_name, id);
- ti_av = proto_tree_add_text(st, tvb, offset + 3, -1, "Attribute Value");
- st = proto_item_add_subtree(ti_av, ett_btsdp_attribute);
-
- size = dissect_sdp_type(st, tvb, offset + 3, &attr_val);
- proto_item_append_text(ti_sa, ", value = %s", attr_val);
-
- if( pinfo->fd->flags.visited ==0) {
- void *val;
- guint8 type;
- guint32 service, service_val;
- btsdp_data_t *service_item;
-
- service_item=se_tree_lookup32(service_table, token);
-
- if(service_item != NULL) {
- switch(id) {
-
- case ATTR_ID_PROTOCOL_DESCRIPTOR_LIST:
- case ATTR_ID_BT_PROFILE_DESCRIPTOR_LIST:
- case ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS:
- get_sdp_data_element(tvb, offset+ 3, id, &type, &val, &service, &service_val);
-
- if( (service == BTSDP_L2CAP_PROTOCOL_UUID)
- || (service == BTSDP_RFCOMM_PROTOCOL_UUID) ) {
- service_item->channel = service_val;
- service_item->protocol = (guint16) service;
- }
- else {
- service_item->service = service;
- }
-
- service_item->flags = 0;
- if(id == ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS) {
- service_item->flags = BTSDP_SECONDARY_CHANNEL_FLAG_MASK;
- }
- break;
-
- case ATTR_ID_SERVICE_CLASS_ID_LIST:
- get_sdp_data_element(tvb, offset+ 3, id, &type, &val, &service, &service_val);
- service_item->service = service;
- break;
-
- case ATTR_ID_GOEP_L2CAP_PSM_GROUP_ID_IP_SUBNET:
- /* GOEP L2CAP PSM? */
- {
- void *psm;
- guint8 *psm_guint8;
-
- get_sdp_data_element(tvb, offset+ 3, id, &type, &psm, &service, &service_val);
- psm_guint8 = psm;
-
- if( (type == 1) && (*psm_guint8 & 0x1) ) {
- service_item->channel = *psm_guint8;
- service_item->protocol = BTSDP_L2CAP_PROTOCOL_UUID;
- service_item->flags = 0;
- }
- }
- break;
- }
-
- if( service_item->service != 0 && service_item->channel != 0 ) {
- service_item->flags |= token >>15; /* set flag when local service */
- tap_queue_packet(btsdp_tap, NULL, (void *) service_item);
- }
- }
- }
-
- proto_item_set_len(ti_sa, size + 3);
- proto_item_set_len(ti_av, size);
-
- return offset+size+3;
+ proto_tree *st, *ti_sa, *ti_av;
+ int size;
+ const char *att_name;
+ guint16 id;
+ char *attr_val;
+
+ id = tvb_get_ntohs(tvb, offset+1);
+ att_name = val_to_str_const(id, vs_general_attribute_id, "Unknown");
+
+ ti_sa = proto_tree_add_text(tree, tvb, offset, -1,
+ "Service Attribute: id = %s (0x%x)", att_name, id);
+ st = proto_item_add_subtree(ti_sa, ett_btsdp_attribute);
+
+ proto_tree_add_text(st, tvb, offset, 3, "Attribute ID: %s (0x%x)", att_name, id);
+ ti_av = proto_tree_add_text(st, tvb, offset + 3, -1, "Attribute Value");
+ st = proto_item_add_subtree(ti_av, ett_btsdp_attribute);
+
+ size = dissect_sdp_type(st, tvb, offset + 3, &attr_val);
+ proto_item_append_text(ti_sa, ", value = %s", attr_val);
+
+ if (!pinfo->fd->flags.visited) {
+ void *val;
+ guint8 type;
+ guint32 service, service_val;
+ btsdp_data_t *service_item;
+
+ service_item = se_tree_lookup32(service_table, token);
+
+ if (service_item != NULL) {
+ switch (id) {
+
+ case ATTR_ID_PROTOCOL_DESCRIPTOR_LIST:
+ case ATTR_ID_BT_PROFILE_DESCRIPTOR_LIST:
+ case ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS:
+ get_sdp_data_element(tvb, offset+ 3, id, &type, &val, &service, &service_val);
+
+ if ((service == BTSDP_L2CAP_PROTOCOL_UUID)
+ || (service == BTSDP_RFCOMM_PROTOCOL_UUID)) {
+ service_item->channel = service_val;
+ service_item->protocol = (guint16) service;
+ }
+ else {
+ service_item->service = service;
+ }
+
+ service_item->flags = 0;
+ if (id == ATTR_ID_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS) {
+ service_item->flags = BTSDP_SECONDARY_CHANNEL_FLAG_MASK;
+ }
+ break;
+
+ case ATTR_ID_SERVICE_CLASS_ID_LIST:
+ get_sdp_data_element(tvb, offset+ 3, id, &type, &val, &service, &service_val);
+ service_item->service = service;
+ break;
+
+ case ATTR_ID_GOEP_L2CAP_PSM_GROUP_ID_IP_SUBNET:
+ /* GOEP L2CAP PSM? */
+ {
+ void *psm;
+ guint8 *psm_guint8;
+
+ get_sdp_data_element(tvb, offset+ 3, id, &type, &psm, &service, &service_val);
+ psm_guint8 = psm;
+
+ if ((type == 1) && (*psm_guint8 & 0x1)) {
+ service_item->channel = *psm_guint8;
+ service_item->protocol = BTSDP_L2CAP_PROTOCOL_UUID;
+ service_item->flags = 0;
+ }
+ }
+ break;
+ }
+
+ if (service_item->service != 0 && service_item->channel != 0) {
+ service_item->flags |= token >>15; /* set flag when local service */
+ tap_queue_packet(btsdp_tap, NULL, (void *) service_item);
+ }
+ }
+ }
+
+ proto_item_set_len(ti_sa, size + 3);
+ proto_item_set_len(ti_av, size);
+
+ return offset+size+3;
}
static int
dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_item *ti;
- proto_tree *st;
- int start_offset = offset, len;
+ proto_item *ti;
+ proto_tree *st;
+ int start_offset = offset, len;
- offset = get_type_length(tvb, offset, &len);
+ offset = get_type_length(tvb, offset, &len);
- ti = proto_tree_add_text(tree, tvb, start_offset, -1, "Attribute List");
- st = proto_item_add_subtree(ti, ett_btsdp_attribute);
+ ti = proto_tree_add_text(tree, tvb, start_offset, -1, "Attribute List");
+ st = proto_item_add_subtree(ti, ett_btsdp_attribute);
- if(!len){
- return offset;
- }
+ if (!len) {
+ return offset;
+ }
- while (offset - start_offset < len) {
- offset = dissect_sdp_service_attribute(st, tvb, offset, pinfo, token);
- }
+ while ((offset - start_offset) < len) {
+ offset = dissect_sdp_service_attribute(st, tvb, offset, pinfo, token);
+ }
- proto_item_set_len(ti, offset - start_offset);
- return offset;
+ proto_item_set_len(ti, offset - start_offset);
+ return offset;
}
@@ -642,21 +744,21 @@ dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset,
static int
dissect_sdp_service_attribute_list_array(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_item *ti;
- proto_tree *st;
- int start_offset, len;
+ proto_item *ti;
+ proto_tree *st;
+ int start_offset, len;
- start_offset=offset;
- offset = get_type_length(tvb, offset, &len);
- ti = proto_tree_add_text(tree, tvb, start_offset, offset-start_offset+len, "Attribute Lists");
- st = proto_item_add_subtree(ti, ett_btsdp_attribute);
+ start_offset = offset;
+ offset = get_type_length(tvb, offset, &len);
+ ti = proto_tree_add_text(tree, tvb, start_offset, offset-start_offset+len, "Attribute Lists");
+ st = proto_item_add_subtree(ti, ett_btsdp_attribute);
- start_offset=offset;
- while(offset-start_offset < len) {
- offset = dissect_sdp_service_attribute_list(st, tvb, offset, pinfo, token);
- }
+ start_offset = offset;
+ while (offset-start_offset < len) {
+ offset = dissect_sdp_service_attribute_list(st, tvb, offset, pinfo, token);
+ }
- return offset;
+ return offset;
}
@@ -664,350 +766,348 @@ dissect_sdp_service_attribute_list_array(proto_tree *tree, tvbuff_t *tvb, int of
static int
dissect_sdp_service_search_attribute_response(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_tree_add_item(tree, hf_ssares_al_bytecount, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
+ proto_tree_add_item(tree, hf_ssares_al_bytecount, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
- offset += dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo, token);
+ offset += dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo, token);
- return offset;
+ return offset;
}
static int
dissect_sdp_service_search_attribute_request(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_tree *st;
- proto_item *ti;
- int start_offset;
- int size, bytes_to_go;
- char *str;
- btsdp_data_t *service_item = NULL;
-
- start_offset = offset;
- ti = proto_tree_add_text(t, tvb, offset, 2, "Service Search Pattern");
- st = proto_item_add_subtree(ti, ett_btsdp_attribute);
-
- offset = get_type_length(tvb, offset, &bytes_to_go);
- proto_item_set_len(ti, offset - start_offset + bytes_to_go);
-
- while(bytes_to_go>0) {
- if (pinfo->fd->flags.visited == 0) {
- service_item=se_tree_lookup32(service_table, token);
-
- if(service_item == NULL) {
- service_item=se_alloc(sizeof(btsdp_data_t));
- se_tree_insert32(service_table, token, service_item);
- }
- service_item->channel = 0;
- service_item->service = 0;
- }
-
- size = dissect_sdp_type(st, tvb, offset, &str);
- proto_item_append_text(st, " %s", str);
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s", str);
-
- if (size < 1) {
- break;
- }
- offset+=size;
- bytes_to_go-=size;
- }
-
- /* dissect maximum attribute byte count */
- proto_tree_add_text(t, tvb, offset, 2, "Maximum Attribute Byte Count: %d", tvb_get_ntohs(tvb, offset));
- offset+=2;
-
- offset += dissect_attribute_id_list(t, tvb, offset, pinfo);
-
- proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
-
- return offset;
+ proto_tree *st;
+ proto_item *ti;
+ int start_offset;
+ int size, bytes_to_go;
+ char *str;
+
+ start_offset = offset;
+ ti = proto_tree_add_text(t, tvb, offset, 2, "Service Search Pattern");
+ st = proto_item_add_subtree(ti, ett_btsdp_attribute);
+
+ offset = get_type_length(tvb, offset, &bytes_to_go);
+ proto_item_set_len(ti, offset - start_offset + bytes_to_go);
+
+ while (bytes_to_go > 0) {
+ btsdp_data_t *service_item;
+ if (!pinfo->fd->flags.visited) {
+ service_item = se_tree_lookup32(service_table, token);
+
+ if (service_item == NULL) {
+ service_item = se_alloc0(sizeof(btsdp_data_t));
+ se_tree_insert32(service_table, token, service_item);
+ }
+ service_item->channel = 0;
+ service_item->service = 0;
+ }
+
+ size = dissect_sdp_type(st, tvb, offset, &str);
+ proto_item_append_text(st, " %s", str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", str);
+
+ if (size < 1) {
+ break;
+ }
+ offset += size;
+ bytes_to_go -= size;
+ }
+
+ /* dissect maximum attribute byte count */
+ proto_tree_add_text(t, tvb, offset, 2, "Maximum Attribute Byte Count: %d", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ offset += dissect_attribute_id_list(t, tvb, offset, pinfo);
+
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
+
+ return offset;
}
static int
dissect_sdp_service_attribute_response(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- proto_tree_add_text(t, tvb, offset, 2, "Attribute List Byte Count: %d",
- tvb_get_ntohs(tvb, offset));
- offset+=2;
+ proto_tree_add_text(t, tvb, offset, 2, "Attribute List Byte Count: %d",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
- offset = dissect_sdp_service_attribute_list(t, tvb, offset, pinfo, token);
+ offset = dissect_sdp_service_attribute_list(t, tvb, offset, pinfo, token);
- proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
- offset+=tvb_length_remaining(tvb, offset);
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
+ offset += tvb_length_remaining(tvb, offset);
- return offset;
+ return offset;
}
static int
dissect_sdp_service_attribute_request(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- proto_tree_add_text(t, tvb, offset, 4, "Service Record Handle: 0x%x",
- tvb_get_ntohl(tvb, offset));
- offset+=4;
+ proto_tree_add_text(t, tvb, offset, 4, "Service Record Handle: 0x%x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
- proto_tree_add_text(t, tvb, offset, 2, "Maximum Attribute Byte Count: %d",
- tvb_get_ntohs(tvb, offset));
- offset+=2;
+ proto_tree_add_text(t, tvb, offset, 2, "Maximum Attribute Byte Count: %d",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
- offset += dissect_attribute_id_list(t, tvb, offset, pinfo);
+ offset += dissect_attribute_id_list(t, tvb, offset, pinfo);
- proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
- offset+=tvb_length_remaining(tvb, offset);
- return offset;
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
+ offset += tvb_length_remaining(tvb, offset);
+ return offset;
}
static int
dissect_sdp_service_search_request(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
- int start_offset, bytes_to_go, size;
- proto_item *ti;
- proto_tree *st;
+ int start_offset, bytes_to_go, size;
+ proto_item *ti;
+ proto_tree *st;
- start_offset=offset;
+ start_offset = offset;
- ti = proto_tree_add_text(t, tvb, offset, 2, "Service Search Pattern");
- st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern);
+ ti = proto_tree_add_text(t, tvb, offset, -1, "Service Search Pattern");
+ st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern);
- offset = get_type_length(tvb, offset, &bytes_to_go);
- proto_item_set_len(ti, offset - start_offset + bytes_to_go);
+ offset = get_type_length(tvb, offset, &bytes_to_go);
+ proto_item_set_len(ti, offset - start_offset + bytes_to_go);
- while(bytes_to_go>0){
- char *str;
- btsdp_data_t *service_item = NULL;
+ while (bytes_to_go > 0) {
+ char *str;
- if (pinfo->fd->flags.visited == 0) {
- guint32 service, service_val;
- guint8 type;
- void *val = NULL;
+ if (!pinfo->fd->flags.visited) {
+ btsdp_data_t *service_item;
+ guint32 service, service_val; /* dummy */
+ guint8 type;
+ void *val = NULL;
- service_item=se_tree_lookup32(service_table, token);
+ service_item = se_tree_lookup32(service_table, token);
- if(service_item == NULL) {
- service_item=se_alloc(sizeof(btsdp_data_t));
- se_tree_insert32(service_table, token, service_item);
- }
- service_item->channel = 0;
- service_item->service = 0;
+ if (service_item == NULL) {
+ service_item = se_alloc0(sizeof(btsdp_data_t));
+ se_tree_insert32(service_table, token, service_item);
+ }
- get_sdp_data_element(tvb, offset, 4, &type, &val, &service, &service_val);
+ get_sdp_data_element(tvb, offset, 4, &type, &val, &service, &service_val);
- if( type==3 && val != NULL)
- service_item->service = *((guint32 *) val);
- }
+ if ((type == 3) && (val != NULL))
+ service_item->service = *((guint32 *) val); /* "short UUID" */
+ }
- size = dissect_sdp_type(st, tvb, offset, &str);
+ size = dissect_sdp_type(st, tvb, offset, &str);
- proto_item_append_text(st, " %s", str);
+ proto_item_append_text(st, " %s", str);
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s", str);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", str);
- if (size < 1) {
- break;
- }
- offset+=size;
- bytes_to_go-=size;
- }
+ if (size < 1) {
+ break;
+ }
+ offset += size;
+ bytes_to_go -= size;
+ }
- /* dissect maximum service record count */
- proto_tree_add_text(t, tvb, offset, 2, "Maximum Service Record Count: %d",
- tvb_get_ntohs(tvb, offset));
- offset+=2;
+ /* dissect maximum service record count */
+ proto_tree_add_text(t, tvb, offset, 2, "Maximum Service Record Count: %d",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
- proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
- offset+=tvb_length_remaining(tvb, offset);
- return offset;
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
+ offset += tvb_length_remaining(tvb, offset);
+ return offset;
}
static int
dissect_sdp_service_search_response(proto_tree *t, tvbuff_t *tvb, int offset)
{
- proto_tree *st;
- proto_item *ti;
- gint curr_count;
+ proto_tree *st;
+ proto_item *ti;
+ gint curr_count;
- proto_tree_add_item(t, hf_ssr_total_count, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset+=2;
+ proto_tree_add_item(t, hf_ssr_total_count, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
- curr_count = tvb_get_ntohs(tvb, offset);
- proto_tree_add_item(t, hf_ssr_current_count, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset+=2;
+ curr_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(t, hf_ssr_current_count, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
- ti = proto_tree_add_text(t, tvb, offset,
- curr_count * 4, "Service Record Handle List");
- st = proto_item_add_subtree(ti, ett_btsdp_ssr);
+ ti = proto_tree_add_text(t, tvb, offset,
+ curr_count * 4, "Service Record Handle List");
+ st = proto_item_add_subtree(ti, ett_btsdp_ssr);
- while(curr_count>0){
- proto_tree_add_text(st, tvb, offset, 4, "0x%x", tvb_get_ntohl(tvb, offset));
- offset+=4;
- curr_count--;
- }
+ while (curr_count > 0) {
+ proto_tree_add_text(st, tvb, offset, 4, "0x%x", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ curr_count -= 1;
+ }
- proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
- offset+=tvb_length_remaining(tvb, offset);
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
+ offset += tvb_length_remaining(tvb, offset);
- return offset;
+ return offset;
}
static int
dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_item *ti;
- proto_tree *st;
- guint8 pdu;
- guint16 acl_handle;
- guint32 token;
- const char *pdu_name;
- int offset=0;
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP");
-
- ti = proto_tree_add_item(tree, proto_btsdp, tvb, 0, -1, ENC_NA);
- st = proto_item_add_subtree(ti, ett_btsdp);
-
- /* pdu id */
- pdu = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(st, hf_pduid, tvb, offset, 1, ENC_BIG_ENDIAN);
- pdu_name = val_to_str(pdu, vs_pduid, "Unknown");
- switch (pinfo->p2p_dir) {
-
- case P2P_DIR_SENT:
- col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
- break;
-
- case P2P_DIR_RECV:
- col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
- break;
-
- case P2P_DIR_UNKNOWN:
- col_clear(pinfo->cinfo, COL_INFO);
- break;
-
- default:
- col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
- pinfo->p2p_dir);
- break;
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", pdu_name);
- proto_item_append_text(ti, ": %s (0x%x)", pdu_name, pdu);
- offset++;
-
- /* tid */
- proto_tree_add_item(st, hf_tid, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset+=2;
-
- /* plen */
- proto_tree_add_item(st, hf_plen, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset+=2;
-
- acl_handle = ((btl2cap_data_t *) pinfo->private_data)->chandle;
- if( pdu & 0x01)
- token = acl_handle | ((pinfo->p2p_dir != P2P_DIR_RECV)?0x8000:0x0000);
- else
- token = acl_handle | ((pinfo->p2p_dir == P2P_DIR_RECV)?0x8000:0x0000);
-
- switch(pdu) {
- case 0x1:
- offset=dissect_sdp_error_response(st, tvb, offset);
- break;
- case 0x2:
- offset=dissect_sdp_service_search_request(st, tvb, offset, pinfo, token);
- break;
- case 0x3:
- offset=dissect_sdp_service_search_response(st, tvb, offset);
- break;
- case 0x4:
- offset=dissect_sdp_service_attribute_request(st, tvb, offset, pinfo);
- break;
- case 0x5:
- offset=dissect_sdp_service_attribute_response(st, tvb, offset, pinfo, token);
- break;
- case 0x6:
- offset=dissect_sdp_service_search_attribute_request(st, tvb, offset, pinfo, token);
- break;
- case 07:
- offset=dissect_sdp_service_search_attribute_response(st, tvb, offset, pinfo, token);
- break;
- }
+ proto_item *ti;
+ proto_tree *st;
+ guint8 pdu;
+ guint16 acl_handle;
+ guint32 token;
+ const char *pdu_name;
+ int offset = 0;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDP");
+
+ ti = proto_tree_add_item(tree, proto_btsdp, tvb, 0, -1, ENC_NA);
+ st = proto_item_add_subtree(ti, ett_btsdp);
+
+ /* pdu id */
+ pdu = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(st, hf_pduid, tvb, offset, 1, ENC_BIG_ENDIAN);
+ pdu_name = val_to_str_const(pdu, vs_pduid, "Unknown");
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ col_add_str(pinfo->cinfo, COL_INFO, "Sent ");
+ break;
+
+ case P2P_DIR_RECV:
+ col_add_str(pinfo->cinfo, COL_INFO, "Rcvd ");
+ break;
+
+ case P2P_DIR_UNKNOWN:
+ col_clear(pinfo->cinfo, COL_INFO);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
+ pinfo->p2p_dir);
+ break;
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", pdu_name);
+ proto_item_append_text(ti, ": %s (0x%x)", pdu_name, pdu);
+ offset += 1;
+
+ /* tid */
+ proto_tree_add_item(st, hf_tid, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ /* plen */
+ proto_tree_add_item(st, hf_plen, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ acl_handle = ((btl2cap_data_t *) pinfo->private_data)->chandle;
+ if (pdu & 0x01)
+ token = acl_handle | ((pinfo->p2p_dir != P2P_DIR_RECV)?0x8000:0x0000);
+ else
+ token = acl_handle | ((pinfo->p2p_dir == P2P_DIR_RECV)?0x8000:0x0000);
+
+ switch (pdu) {
+ case 0x1:
+ offset = dissect_sdp_error_response(st, tvb, offset);
+ break;
+ case 0x2:
+ offset = dissect_sdp_service_search_request(st, tvb, offset, pinfo, token);
+ break;
+ case 0x3:
+ offset = dissect_sdp_service_search_response(st, tvb, offset);
+ break;
+ case 0x4:
+ offset = dissect_sdp_service_attribute_request(st, tvb, offset, pinfo);
+ break;
+ case 0x5:
+ offset = dissect_sdp_service_attribute_response(st, tvb, offset, pinfo, token);
+ break;
+ case 0x6:
+ offset = dissect_sdp_service_search_attribute_request(st, tvb, offset, pinfo, token);
+ break;
+ case 07:
+ offset = dissect_sdp_service_search_attribute_response(st, tvb, offset, pinfo, token);
+ break;
+ }
return offset;
}
void
proto_register_btsdp(void)
{
- static hf_register_info hf[] = {
- {&hf_pduid,
- {"PDU", "btsdp.pdu",
- FT_UINT8, BASE_HEX, VALS(vs_pduid), 0,
- "PDU type", HFILL}
- },
- {&hf_tid,
- {"Transaction Id", "btsdp.tid",
- FT_UINT16, BASE_HEX, NULL, 0,
- NULL, HFILL}
- },
- {&hf_plen,
- {"Parameter Length", "btsdp.len",
- FT_UINT16, BASE_DEC, NULL, 0,
- NULL, HFILL}
- },
- {&hf_error_code,
- {"Error Code", "btsdp.error_code",
- FT_UINT16, BASE_HEX, NULL, 0,
- NULL, HFILL}
- },
- {&hf_ssr_total_count,
- {"Total Service Record Count", "btsdp.ssr.total_count",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Total count of service records", HFILL}
- },
- {&hf_ssr_current_count,
- {"Current Service Record Count", "btsdp.ssr.current_count",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Count of service records in this message", HFILL}
- },
- {&hf_ssares_al_bytecount,
- {"Attribute Lists Byte Count", "btsdp.ssares.byte_count",
- FT_UINT16, BASE_DEC, NULL, 0,
- "Count of bytes in attribute list response", HFILL}
- }
- };
-
- /* Setup protocol subtree array */
-
- static gint *ett[] = {
- &ett_btsdp,
- &ett_btsdp_ssr,
- &ett_btsdp_des,
- &ett_btsdp_attribute,
- &ett_btsdp_service_search_pattern,
- &ett_btsdp_attribute_idlist
- };
-
- proto_btsdp = proto_register_protocol("Bluetooth SDP Protocol", "BTSDP", "btsdp");
-
- new_register_dissector("btsdp", dissect_btsdp, proto_btsdp);
-
- btsdp_tap = register_tap("btsdp");
-
- /* Required function calls to register the header fields and subtrees used */
- proto_register_field_array(proto_btsdp, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- service_table=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "mapping of rfcomm channel/l2cap PSM to service uuid");
+ static hf_register_info hf[] = {
+ { &hf_pduid,
+ { "PDU", "btsdp.pdu",
+ FT_UINT8, BASE_HEX, VALS(vs_pduid), 0,
+ "PDU type", HFILL}
+ },
+ { &hf_tid,
+ { "Transaction Id", "btsdp.tid",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ NULL, HFILL}
+ },
+ { &hf_plen,
+ { "Parameter Length", "btsdp.len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL}
+ },
+ { &hf_error_code,
+ { "Error Code", "btsdp.error_code",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ NULL, HFILL}
+ },
+ { &hf_ssr_total_count,
+ { "Total Service Record Count", "btsdp.ssr.total_count",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Total count of service records", HFILL}
+ },
+ { &hf_ssr_current_count,
+ { "Current Service Record Count", "btsdp.ssr.current_count",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Count of service records in this message", HFILL}
+ },
+ { &hf_ssares_al_bytecount,
+ { "Attribute Lists Byte Count", "btsdp.ssares.byte_count",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Count of bytes in attribute list response", HFILL}
+ }
+ };
+
+ /* Setup protocol subtree array */
+
+ static gint *ett[] = {
+ &ett_btsdp,
+ &ett_btsdp_ssr,
+ &ett_btsdp_des,
+ &ett_btsdp_attribute,
+ &ett_btsdp_service_search_pattern,
+ &ett_btsdp_attribute_idlist
+ };
+
+ proto_btsdp = proto_register_protocol("Bluetooth SDP Protocol", "BTSDP", "btsdp");
+
+ new_register_dissector("btsdp", dissect_btsdp, proto_btsdp);
+
+ btsdp_tap = register_tap("btsdp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_btsdp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ service_table = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "mapping of rfcomm channel/l2cap PSM to service uuid");
}
void
proto_reg_handoff_btsdp(void)
{
- dissector_handle_t btsdp_handle;
+ dissector_handle_t btsdp_handle;
- btsdp_handle = find_dissector("btsdp");
- dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle);
+ btsdp_handle = find_dissector("btsdp");
+ dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle);
}
diff --git a/epan/dissectors/packet-btsdp.h b/epan/dissectors/packet-btsdp.h
index f61dedf021..dc2bee3f51 100644
--- a/epan/dissectors/packet-btsdp.h
+++ b/epan/dissectors/packet-btsdp.h
@@ -75,104 +75,6 @@ typedef struct _btsdp_data_t {
(peer device) and/or a secondary PSM */
} btsdp_data_t;
-/* service UUIDs */
-static const value_string vs_service_classes[] = {
- {0x0001, "SDP"},
- {0x0002, "UDP"},
- {0x0003, "RFCOMM"},
- {0x0004, "TCP"},
- {0x0005, "TCS-BIN"},
- {0x0006, "TCS-AT"},
- {0x0008, "OBEX"},
- {0x0009, "IP"},
- {0x000A, "FTP"},
- {0x000C, "HTTP"},
- {0x000E, "WSP"},
- {0x000F, "BNEP"},
- {0x0010, "UPNP"},
- {0x0011, "HIDP"},
- {0x0012, "Hardcopy Control Channel"},
- {0x0014, "Hardcopy Data Channel"},
- {0x0016, "Hardcopy Notification"},
- {0x0017, "AVCTP"},
- {0x0019, "AVDTP"},
- {0x001B, "CMPT"},
- {0x001D, "UDI C-Plane"},
- {0x001E, "MCAP Control Channel"},
- {0x001F, "MCAP Data Channel"},
- {0x0100, "L2CAP"},
- {0x1000, "Service Discovery Server Service Class ID"},
- {0x1001, "Browse Group Descriptor Service Class ID"},
- {0x1002, "Public Browse Group"},
- {0x1101, "Serial Port"},
- {0x1102, "LAN Access Using PPP"},
- {0x1103, "Dialup Networking"},
- {0x1104, "IrMC Sync"},
- {0x1105, "OBEX Object Push"},
- {0x1106, "OBEX File Transfer"},
- {0x1107, "IrMC Sync Command"},
- {0x1108, "Headset"},
- {0x1109, "Cordless Telephony"},
- {0x110A, "Audio Source"},
- {0x110B, "Audio Sink"},
- {0x110C, "A/V Remote Control Target"},
- {0x110D, "Advanced Audio Distribution"},
- {0x110E, "A/V Remote Control"},
- {0x110F, "Video Conferencing"},
- {0x1110, "Intercom"},
- {0x1111, "Fax"},
- {0x1112, "Headset Audio Gateway"},
- {0x1113, "WAP"},
- {0x1114, "WAP client"},
- {0x1115, "PANU"},
- {0x1116, "NAP"},
- {0x1117, "GN"},
- {0x1118, "Direct Printing"},
- {0x1119, "Reference Printing"},
- {0x111A, "Imaging"},
- {0x111B, "Imaging Responder"},
- {0x111C, "Imaging Automatic Archive"},
- {0x111D, "Imaging Referenced Objects"},
- {0x111E, "Handsfree"},
- {0x111F, "Handsfree Audio Gateway"},
- {0x1120, "Direct Printing Reference Objects Service"},
- {0x1121, "Reflected UI"},
- {0x1122, "Basic Printing"},
- {0x1123, "Printing Status"},
- {0x1124, "Human Interface Device Service"},
- {0x1125, "Hardcopy Cable Replacement"},
- {0x1126, "HCR Print"},
- {0x1127, "HCR Scan"},
- {0x1128, "Common ISDN Access"},
- {0x1129, "Video Conferencing GW"},
- {0x112A, "UDI MT"},
- {0x112B, "UDI TA"},
- {0x112C, "Audio/Video"},
- {0x112D, "SIM Access"},
- {0x112E, "Phonebook Access client"},
- {0x112F, "Phonebook Access server"},
- {0x1130, "Phonebook Access Profile"},
- {0x1131, "Headset - HS"},
- {0x1132, "Message Access Server"},
- {0x1133, "Message Notification Server"},
- {0x1134, "Message Access Profile"},
- {0x1200, "PnP Information"},
- {0x1201, "Generic Networking"},
- {0x1202, "Generic File Transfer"},
- {0x1203, "Generic Audio"},
- {0x1204, "Generic Telephony"},
- {0x1205, "UPNP_Service"},
- {0x1206, "UPNP_IP_Service"},
- {0x1300, "ESDP_UPNP_IP_PAN"},
- {0x1301, "ESDP_UPNP_IP_LAP"},
- {0x1302, "ESDP_UPNP_L2CAP"},
- {0x1303, "Video Source"},
- {0x1304, "Video Sink"},
- {0x1305, "Video Distribution"},
- {0x1400, "Health Device Profile"},
- {0x1401, "Health Device Source"},
- {0x1402, "Health Device Sink"},
- {0, NULL}
-};
+extern value_string_ext vs_service_classes_ext;
#endif