summaryrefslogtreecommitdiff
path: root/src/sdp-client.c
diff options
context:
space:
mode:
authorArchie Pusaka <apusaka@chromium.org>2020-03-02 12:07:31 +0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-03-02 14:13:17 -0800
commitc730f68303d73f987dda829c17360a11308a046c (patch)
tree2c538458aa2b066d5e47febec9b17d65f3622e24 /src/sdp-client.c
parent2fa0703398125bc6a2aa25be05324f656ddc494f (diff)
downloadbluez-c730f68303d73f987dda829c17360a11308a046c.tar.gz
src/profile: Ensure class UUID matches before connecting profile
According to bluetooth spec Ver 5.1, Vol 3, Part B, 4.7.2, there might be multiple service records returned in a SDP Service Search Attribute Response. Also, according to 2.5.2, the service pattern can match any UUID contained within the service record, it doesn't have to match only some specific attributes of the record. Therefore, before using the service record to connect to any profile, first we must check that the service class ID of the service record matches with whatever UUID specified in the service pattern we are looking for. This patch checks the service class ID of the records against the requested UUID whenever bt_search_service() is called and filter out the ones that don't match. For the alternative where filtering is not applied, use the method bt_search().
Diffstat (limited to 'src/sdp-client.c')
-rw-r--r--src/sdp-client.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/src/sdp-client.c b/src/sdp-client.c
index 413cf30ec..b92a083af 100644
--- a/src/sdp-client.c
+++ b/src/sdp-client.c
@@ -143,6 +143,7 @@ struct search_context {
gpointer user_data;
uuid_t uuid;
guint io_id;
+ gboolean filter_svc_class;
};
static GSList *context_list = NULL;
@@ -195,6 +196,16 @@ static void search_completed_cb(uint8_t type, uint16_t status,
rsp += recsize;
bytesleft -= recsize;
+ /* Check whether service class ID matches some specified uuid.
+ * If the record is missing service class ID, svclass will be
+ * all zero, and thus will be unequal to the requested uuid.
+ */
+ if (ctxt->filter_svc_class &&
+ sdp_uuid_cmp(&ctxt->uuid, &rec->svclass) != 0) {
+ sdp_record_free(rec);
+ continue;
+ }
+
recs = sdp_list_append(recs, rec);
} while (scanned < (ssize_t) size && bytesleft > 0);
@@ -338,7 +349,28 @@ static int create_search_context(struct search_context **ctxt,
return 0;
}
-int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
+static int create_search_context_full(struct search_context **ctxt,
+ const bdaddr_t *src,
+ const bdaddr_t *dst,
+ uuid_t *uuid, uint16_t flags,
+ void *user_data, bt_callback_t cb,
+ bt_destroy_t destroy,
+ gboolean filter_svc_class)
+{
+ int err = create_search_context(ctxt, src, dst, uuid, flags);
+
+ if (err < 0)
+ return err;
+
+ (*ctxt)->cb = cb;
+ (*ctxt)->destroy = destroy;
+ (*ctxt)->user_data = user_data;
+ (*ctxt)->filter_svc_class = filter_svc_class;
+
+ return 0;
+}
+
+int bt_search(const bdaddr_t *src, const bdaddr_t *dst,
uuid_t *uuid, bt_callback_t cb, void *user_data,
bt_destroy_t destroy, uint16_t flags)
{
@@ -348,13 +380,32 @@ int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
if (!cb)
return -EINVAL;
- err = create_search_context(&ctxt, src, dst, uuid, flags);
+ /* The resulting service class ID doesn't have to match uuid */
+ err = create_search_context_full(&ctxt, src, dst, uuid, flags,
+ user_data, cb, destroy, FALSE);
if (err < 0)
return err;
- ctxt->cb = cb;
- ctxt->destroy = destroy;
- ctxt->user_data = user_data;
+ context_list = g_slist_append(context_list, ctxt);
+
+ return 0;
+}
+
+int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
+ uuid_t *uuid, bt_callback_t cb, void *user_data,
+ bt_destroy_t destroy, uint16_t flags)
+{
+ struct search_context *ctxt = NULL;
+ int err;
+
+ if (!cb)
+ return -EINVAL;
+
+ /* The resulting service class ID need to match uuid */
+ err = create_search_context_full(&ctxt, src, dst, uuid, flags,
+ user_data, cb, destroy, TRUE);
+ if (err < 0)
+ return err;
context_list = g_slist_append(context_list, ctxt);