aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-btsdp.c
diff options
context:
space:
mode:
authorKovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>2011-01-02 08:13:40 +0000
committerKovarththanan Rajaratnam <kovarththanan.rajaratnam@gmail.com>2011-01-02 08:13:40 +0000
commit46dd093b945d4bc088741e22b9c0a87024fc6fe4 (patch)
tree5752f0f5c73ffd81be6abe6c2331f8e2ce71dbf5 /epan/dissectors/packet-btsdp.c
parent388453b79dcc220ced63cd854924cd0ad1411077 (diff)
From Allan M. Madsen via. bug 5445:
Bluetooth profiles and protocols above RFCOMM and L2CAP can not be dissected correctly because the required information (server channel and dynamic PSM value mappings to services/profiles) about the type of data carried in the payload is not available. RFCOMM is currently hardcoded to handoff all payload data to the obex dissector though it may carry e.g. handsfree, dial-up networking or serial port profile related data. The patch consists of modifcations to the following dissectors: btsdp: Extraction of RFCOMM server channel and L2CAP dynamic PSM with service mapping is provided to RFCOMM and L2CAP through a tap interface. In addition, the packet list info is beautyfied and extended with more details for better overview. btl2cap: Adds a new dissector table with services and dynamic PSM mapping which is filled by a tap listner catching the info from btsdp. More info added to packet list. btrfcomm: Adds a new dissector table with services and server channel mapping which is filled by a tap listner catching the info from btsdp. Dissectors for handsfree, dial-up netorking and serial port profiles (all based on RFCOMM) are also added. btobex: Registers several obex based profiles (e.g. obex push, file transfer, basic printing etc.) in both RFCOMM and L2CAP. Some cleanup. svn path=/trunk/; revision=35323
Diffstat (limited to 'epan/dissectors/packet-btsdp.c')
-rw-r--r--epan/dissectors/packet-btsdp.c530
1 files changed, 338 insertions, 192 deletions
diff --git a/epan/dissectors/packet-btsdp.c b/epan/dissectors/packet-btsdp.c
index 59454a548b..2168dd67bc 100644
--- a/epan/dissectors/packet-btsdp.c
+++ b/epan/dissectors/packet-btsdp.c
@@ -37,7 +37,9 @@
#include <epan/value_string.h>
#include <epan/emem.h>
#include <etypes.h>
-#include "packet-btl2cap.h"
+#include <epan/tap.h>
+#include <epan/dissectors/packet-btsdp.h>
+#include <epan/dissectors/packet-btl2cap.h>
/* Initialize the protocol and registered fields */
static int proto_btsdp = -1;
@@ -58,135 +60,71 @@ static gint ett_btsdp_attribute = -1;
static gint ett_btsdp_service_search_pattern = -1;
static gint ett_btsdp_attribute_idlist = -1;
+static int btsdp_tap = -1;
+
+/* This table maps rfcomm service channels and dynamic l2cap
+ * PSM's to profile service uuids.
+ * The same table is used both for local and remote servers.
+ * For received CIDs we mask the cid with 0x8000 in this table
+ */
+static emem_tree_t *service_table = NULL;
+
static const value_string vs_pduid[] = {
- {0x1, "SDP_ErrorResponse"},
- {0x2, "SDP_ServiceSearchRequest"},
- {0x3, "SDP_ServiceSearchResponse"},
- {0x4, "SDP_ServiceAttributeRequest"},
- {0x5, "SDP_ServiceAttributeResponse"},
- {0x6, "SDP_ServiceSearchAttributeRequest"},
- {0x7, "SDP_ServiceSearchAttributeResponse"},
+ {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}
};
static const value_string vs_general_attribute_id[] = {
- {0x0000, "ServiceRecordHandle"},
- {0x0001, "ServiceClassIDList"},
- {0x0002, "ServiceRecordState"},
- {0x0003, "ServiceID"},
- {0x0004, "ProtocolDescriptorList"},
- {0x0005, "BrowseGroupList"},
- {0x0006, "LanguageBaseAttributeIDList"},
- {0x0007, "ServiceinfoTimeToLive"},
- {0x0008, "ServiceAvailability"},
- {0x0009, "BluetoothProfileDescriptorList"},
- {0x000a, "DocumentationURL"},
- {0x000b, "ClientExecutableURL"},
- {0x000c, "IconURL"},
+ {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, "Service Provider"},
+ {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}
};
-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, "HardcopyControlChannel"},
- {0x0014, "HardcopyDataChannel"},
- {0x0016, "HardcopyNotification"},
- {0x0017, "AVCTP"},
- {0x0019, "AVDTP"},
- {0x001B, "CMPT"},
- {0x001D, "UDI_C-Plane"},
- {0x001E, "MCAPControlChannel"},
- {0x001F, "MCAPDataChannel"},
- {0x0100, "L2CAP"},
- {0x1000, "ServiceDiscoveryServerServiceClassID"},
- {0x1001, "BrowseGroupDescriptorServiceClassID"},
- {0x1002, "PublicBrowseGroup"},
- {0x1101, "SerialPort"},
- {0x1102, "LANAccessUsingPPP"},
- {0x1103, "DialupNetworking"},
- {0x1104, "IrMCSync"},
- {0x1105, "OBEXObjectPush"},
- {0x1106, "OBEXFileTransfer"},
- {0x1107, "IrMCSyncCommand"},
- {0x1108, "Headset"},
- {0x1109, "CordlessTelephony"},
- {0x110A, "AudioSource"},
- {0x110B, "AudioSink"},
- {0x110C, "A/V_RemoteControlTarget"},
- {0x110D, "AdvancedAudioDistribution"},
- {0x110E, "A/V_RemoteControl"},
- {0x110F, "VideoConferencing"},
- {0x1110, "Intercom"},
- {0x1111, "Fax"},
- {0x1112, "HeadsetAudioGateway"},
- {0x1113, "WAP"},
- {0x1114, "WAP_CLIENT"},
- {0x1115, "PANU"},
- {0x1116, "NAP"},
- {0x1117, "GN"},
- {0x1118, "DirectPrinting"},
- {0x1119, "ReferencePrinting"},
- {0x111A, "Imaging"},
- {0x111B, "ImagingResponder"},
- {0x111C, "ImagingAutomaticArchive"},
- {0x111D, "ImagingReferencedObjects"},
- {0x111E, "Handsfree"},
- {0x111F, "HandsfreeAudioGateway"},
- {0x1120, "DirectPrintingReferenceObjectsService"},
- {0x1121, "ReflectedUI"},
- {0x1122, "BasicPrinting"},
- {0x1123, "PrintingStatus"},
- {0x1124, "HumanInterfaceDeviceService"},
- {0x1125, "HardcopyCableReplacement"},
- {0x1126, "HCR_Print"},
- {0x1127, "HCR_Scan"},
- {0x1128, "Common_ISDN_Access"},
- {0x1129, "VideoConferencingGW"},
- {0x112A, "UDI_MT"},
- {0x112B, "UDI_TA"},
- {0x112C, "Audio/Video"},
- {0x112D, "SIM_Access"},
- {0x112E, "PBAP client"},
- {0x112F, "PBAP server"},
- {0x1130, "PBAP"},
- {0x1200, "PnPInformation"},
- {0x1201, "GenericNetworking"},
- {0x1202, "GenericFileTransfer"},
- {0x1203, "GenericAudio"},
- {0x1204, "GenericTelephony"},
- {0x1205, "UPNP_Service"},
- {0x1206, "UPNP_IP_Service"},
- {0x1300, "ESDP_UPNP_IP_PAN"},
- {0x1301, "ESDP_UPNP_IP_LAP"},
- {0x1302, "ESDP_UPNP_L2CAP"},
- {0x1303, "VideoSource"},
- {0x1304, "VideoSink"},
- {0x1305, "VideoDistribution"},
- {0x1400, "Medical Device Profile"},
- {0x1401, "MDP Source"},
- {0x1402, "MDP Sink"},
- {0, NULL}
-};
-
-
-
static int
get_type_length(tvbuff_t *tvb, int offset, int *length)
{
@@ -262,7 +200,7 @@ get_int_by_size(tvbuff_t *tvb, int off, int size)
static int
-dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int offset)
+dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
proto_item *ti;
proto_tree *st;
@@ -271,7 +209,7 @@ dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int offset)
const char *att_name;
start_offset=offset;
- ti = proto_tree_add_text(t, tvb, offset, 2, "AttributeIDList");
+ 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);
@@ -287,8 +225,13 @@ dissect_attribute_id_list(proto_tree *t, tvbuff_t *tvb, int offset)
proto_tree_add_text(st, tvb, offset, 3, "%s (0x%04x)", att_name, id);
offset+=3;
bytes_to_go-=3;
- } else if (byte0 == 0x0a) { /* 32 bit attribute range */
+ 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));
@@ -311,6 +254,121 @@ dissect_sdp_error_response(proto_tree *t, tvbuff_t *tvb, int offset) {
return offset;
}
+static int
+get_sdp_type(tvbuff_t *tvb, int offset, guint16 id, guint8 *type, guint8 **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;
+
+ 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_type(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;
+}
+
static int
dissect_sdp_type(proto_tree *t, tvbuff_t *tvb, int offset, char **attr_val)
@@ -361,25 +419,21 @@ dissect_sdp_type(proto_tree *t, tvbuff_t *tvb, int offset, char **attr_val)
break;
}
case 3: {
+ guint32 id;
+ const char *uuid_name;
char *ptr = tvb_bytes_to_str(tvb, offset, size);
if(size == 2){
-
- guint16 id = tvb_get_ntohs(tvb, offset);
- const char *uuid_name = val_to_str(id, vs_service_classes, "Unknown");
-
- 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, "UUID:%s (0x%s) ", uuid_name, ptr);
- }
+ 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,
- "UUID 0x%s ", ptr);
- if(strpos<MAX_SDP_LEN){
- strpos+=g_snprintf(str+strpos, MAX_SDP_LEN-strpos, "0x%s ", ptr);
- }
+ 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;
}
@@ -458,9 +512,8 @@ 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)
+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;
@@ -474,15 +527,60 @@ dissect_sdp_service_attribute(proto_tree *tree, tvbuff_t *tvb, int offset)
"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) {
+ guint8 *val, type;
+ guint32 service, service_val;
+ btsdp_data_t *service_item;
+
+ service_item=se_tree_lookup32(service_table, token);
+
+ if(service_item != NULL) {
+ if(id == 4 || (id == 9) || (id == 0xd)) { /* profile/protocol discriptor list/additional protocol list */
+ get_sdp_type(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 == 0xd) {
+ service_item->flags = BTSDP_SECONDARY_CHANNEL_FLAG_MASK;
+ }
+ }
+ else if( id == 1) { /* service class id list */
+ get_sdp_type(tvb, offset+ 3, id, &type, &val, &service, &service_val);
+ service_item->service = service;
+ }
+ else if(id == 0x200) { /* GOEP L2CAP PSM? */
+ guint16 *psm;
+
+ get_sdp_type(tvb, offset+ 3, id, &type, (guint8 **) &psm, &service, &service_val);
+
+ if( (type == 1) && (*psm > 0x1000) && (*psm & 0x1) ) {
+ service_item->channel = *psm;
+ service_item->protocol = BTSDP_L2CAP_PROTOCOL_UUID;
+ service_item->flags = 0;
+ }
+ }
+
+ 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);
@@ -492,7 +590,7 @@ dissect_sdp_service_attribute(proto_tree *tree, tvbuff_t *tvb, int offset)
static int
-dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset)
+dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 token)
{
proto_item *ti;
proto_tree *st;
@@ -500,7 +598,7 @@ dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset)
offset = get_type_length(tvb, offset, &len);
- ti = proto_tree_add_text(tree, tvb, start_offset, -1, "AttributeList");
+ ti = proto_tree_add_text(tree, tvb, start_offset, -1, "Attribute List");
st = proto_item_add_subtree(ti, ett_btsdp_attribute);
if(!len){
@@ -508,7 +606,7 @@ dissect_sdp_service_attribute_list(proto_tree *tree, tvbuff_t *tvb, int offset)
}
while (offset - start_offset < len) {
- offset = dissect_sdp_service_attribute(st, tvb, offset);
+ offset = dissect_sdp_service_attribute(st, tvb, offset, pinfo, token);
}
proto_item_set_len(ti, offset - start_offset);
@@ -518,7 +616,7 @@ 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)
+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;
@@ -526,12 +624,12 @@ dissect_sdp_service_attribute_list_array(proto_tree *tree, tvbuff_t *tvb, int of
start_offset=offset;
offset = get_type_length(tvb, offset, &len);
- ti = proto_tree_add_text(tree, tvb, start_offset, offset-start_offset+len, "AttributeLists");
+ 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);
+ offset = dissect_sdp_service_attribute_list(st, tvb, offset, pinfo, token);
}
return offset;
@@ -540,38 +638,50 @@ 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)
+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, FALSE);
offset += 2;
- offset += dissect_sdp_service_attribute_list_array(tree, tvb, offset);
+ offset += dissect_sdp_service_attribute_list_array(tree, tvb, offset, pinfo, token);
return offset;
}
static int
-dissect_sdp_service_search_attribute_request(proto_tree *t, tvbuff_t *tvb, int offset)
+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, "ServiceSearchPattern");
+ 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;
}
@@ -580,27 +690,26 @@ dissect_sdp_service_search_attribute_request(proto_tree *t, tvbuff_t *tvb, int o
}
/* dissect maximum attribute byte count */
- proto_tree_add_text(t, tvb, offset, 2, "MaximumAttributeByteCount: %d", tvb_get_ntohs(tvb, offset));
+ 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);
-
- proto_tree_add_text(t, tvb, offset, -1, "ContinuationState");
+ 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)
+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, "AttributeListByteCount: %d",
+ 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);
+ offset = dissect_sdp_service_attribute_list(t, tvb, offset, pinfo, token);
- proto_tree_add_text(t, tvb, offset, -1, "ContinuationState");
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
offset+=tvb_length_remaining(tvb, offset);
return offset;
@@ -608,33 +717,34 @@ dissect_sdp_service_attribute_response(proto_tree *t, tvbuff_t *tvb, int offset)
static int
-dissect_sdp_service_attribute_request(proto_tree *t, tvbuff_t *tvb, int offset)
+dissect_sdp_service_attribute_request(proto_tree *t, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
- proto_tree_add_text(t, tvb, offset, 4, "ServiceRecordHandle: 0x%x",
+ 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, "MaximumAttributeByteCount: %d",
+ 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);
+ offset += dissect_attribute_id_list(t, tvb, offset, pinfo);
- proto_tree_add_text(t, tvb, offset, -1, "ContinuationState");
+ 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)
+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;
+ int start_offset, bytes_to_go, size;
proto_item *ti;
proto_tree *st;
start_offset=offset;
- ti = proto_tree_add_text(t, tvb, offset, 2, "ServiceSearchPattern");
+
+ ti = proto_tree_add_text(t, tvb, offset, 2, "Service Search Pattern");
st = proto_item_add_subtree(ti, ett_btsdp_service_search_pattern);
offset = get_type_length(tvb, offset, &bytes_to_go);
@@ -642,8 +752,33 @@ dissect_sdp_service_search_request(proto_tree *t, tvbuff_t *tvb, int offset)
while(bytes_to_go>0){
char *str;
+ btsdp_data_t *service_item = NULL;
+
+ if (pinfo->fd->flags.visited == 0) {
+ guint32 service, service_val;
+ guint8 type, *val = NULL;
+
+ 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;
+
+ get_sdp_type(tvb, offset, 4, &type, &val, &service, &service_val);
+
+ if( type==3 && val != NULL)
+ service_item->service = *((guint32 *) val);
+ }
+
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;
}
@@ -652,12 +787,11 @@ dissect_sdp_service_search_request(proto_tree *t, tvbuff_t *tvb, int offset)
}
/* dissect maximum service record count */
-
- proto_tree_add_text(t, tvb, offset, 2, "MaximumServiceRecordCount: %d",
+ 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, "ContinuationState");
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
offset+=tvb_length_remaining(tvb, offset);
return offset;
}
@@ -678,7 +812,7 @@ dissect_sdp_service_search_response(proto_tree *t, tvbuff_t *tvb, int offset)
offset+=2;
ti = proto_tree_add_text(t, tvb, offset,
- curr_count * 4, "ServiceRecordHandleList");
+ curr_count * 4, "Service Record Handle List");
st = proto_item_add_subtree(ti, ett_btsdp_ssr);
while(curr_count>0){
@@ -687,7 +821,7 @@ dissect_sdp_service_search_response(proto_tree *t, tvbuff_t *tvb, int offset)
curr_count--;
}
- proto_tree_add_text(t, tvb, offset, -1, "ContinuationState");
+ proto_tree_add_text(t, tvb, offset, -1, "Continuation State");
offset+=tvb_length_remaining(tvb, offset);
return offset;
@@ -700,7 +834,8 @@ dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_item *ti;
proto_tree *st;
guint8 pdu;
- guint16 plen;
+ guint16 tid, plen, acl_handle;
+ guint32 token;
const char *pdu_name;
int offset=0;
@@ -720,6 +855,7 @@ dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset++;
/* tid */
+ tid = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(st, hf_tid, tvb, offset, 2, FALSE);
offset+=2;
@@ -728,32 +864,37 @@ dissect_btsdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_tree_add_item(st, hf_plen, tvb, offset, 2, FALSE);
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);
+ 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);
+ offset=dissect_sdp_service_attribute_request(st, tvb, offset, pinfo);
break;
case 0x5:
- offset=dissect_sdp_service_attribute_response(st, tvb, offset);
+ offset=dissect_sdp_service_attribute_response(st, tvb, offset, pinfo, token);
break;
case 0x6:
- offset=dissect_sdp_service_search_attribute_request(st, tvb, offset);
+ 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);
+ offset=dissect_sdp_service_search_attribute_response(st, tvb, offset, pinfo, token);
break;
}
}
-
void
proto_register_btsdp(void)
{
@@ -764,34 +905,34 @@ proto_register_btsdp(void)
"PDU type", HFILL}
},
{&hf_tid,
- {"TransactionID", "btsdp.tid",
+ {"Transaction Id", "btsdp.tid",
FT_UINT16, BASE_HEX, NULL, 0,
- "Transaction ID", HFILL}
+ NULL, HFILL}
},
{&hf_plen,
- {"ParameterLength", "btsdp.len",
+ {"Parameter Length", "btsdp.len",
FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL}
},
{&hf_error_code,
- {"ErrorCode", "btsdp.error_code",
+ {"Error Code", "btsdp.error_code",
FT_UINT16, BASE_HEX, NULL, 0,
- "Error Code", HFILL}
+ NULL, HFILL}
},
{&hf_ssr_total_count,
- {"TotalServiceRecordCount", "btsdp.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,
- {"CurrentServiceRecordCount", "btsdp.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}
+ "Count of service records in this message", HFILL}
},
{&hf_ssares_al_bytecount,
- {"AttributeListsByteCount", "btsdp.ssares.byte_count",
+ {"Attribute Lists Byte Count", "btsdp.ssares.byte_count",
FT_UINT16, BASE_DEC, NULL, 0,
- "count of bytes in attribute list response", HFILL}
+ "Count of bytes in attribute list response", HFILL}
}
};
@@ -806,13 +947,17 @@ proto_register_btsdp(void)
&ett_btsdp_attribute_idlist
};
- proto_btsdp = proto_register_protocol("Bluetooth SDP", "BTSDP", "btsdp");
+ proto_btsdp = proto_register_protocol("Bluetooth SDP Protocol", "BTSDP", "btsdp");
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");
}
@@ -824,3 +969,4 @@ proto_reg_handoff_btsdp(void)
btsdp_handle = find_dissector("btsdp");
dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_SDP, btsdp_handle);
}
+