diff options
Diffstat (limited to 'epan/dissectors/packet-btsdp.c')
-rw-r--r-- | epan/dissectors/packet-btsdp.c | 1662 |
1 files changed, 881 insertions, 781 deletions
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); } |