Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Nov 2007 11:57:08 +0000
From:      Iain Hibbert <plunky@rya-online.net>
To:        <freebsd-bluetooth@freebsd.org>
Cc:        maxsim.yevmenkin@gmail.com
Subject:   Re: sdp - SearchService of UUID
Message-ID:  <E1IpN5T-0006Rs-Jv@localhost.localdomain>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi Max,

So, I think this is it..

Attached is a patch to convert sdpd to handle a uuid list. Its for the netbsd version and will require a bit of twiddling in ssar.c and ssr.c to make it apply because of NG_ and sockaddr_l2cap, and you don't have hf.c and hset.c but thats easy enough to ignore.

This seems to be working with SSAR  and SSR from different devices, and a multiple UUID sdp_search query I cobbled together from the local socket. (attached)

Any comments before I go with it?

iain
[-- Attachment #2 --]
--- /usr/src/usr.sbin/sdpd/bgd.c	2006-06-19 16:44:56.000000000 +0100
+++ bgd.c	2007-11-06 09:26:43.000000000 +0000
@@ -98,8 +98,13 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	bgd_profile_descriptor = {
+static uint16_t	bgd_profile_uuids[] = {
 	SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR,
+};
+
+profile_t	bgd_profile_descriptor = {
+	bgd_profile_uuids,
+	sizeof(bgd_profile_uuids),
 	0,
 	(profile_data_valid_p) NULL,
 	(attr_t const * const) &bgd_profile_attrs
--- /usr/src/usr.sbin/sdpd/dun.c	2006-06-19 16:44:56.000000000 +0100
+++ dun.c	2007-11-06 09:28:11.000000000 +0000
@@ -132,8 +132,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	dun_profile_descriptor = {
+static uint16_t dun_profile_uuids[] = {
 	SDP_SERVICE_CLASS_DIALUP_NETWORKING,
+	SDP_SERVICE_CLASS_GENERIC_NETWORKING,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+};
+
+profile_t	dun_profile_descriptor = {
+	dun_profile_uuids,
+	sizeof(dun_profile_uuids),
 	sizeof(sdp_dun_profile_t),
 	common_profile_server_channel_valid,
 	(attr_t const * const) &dun_profile_attrs
--- /usr/src/usr.sbin/sdpd/ftrn.c	2006-06-19 16:44:56.000000000 +0100
+++ ftrn.c	2007-11-06 09:27:02.000000000 +0000
@@ -113,8 +113,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	ftrn_profile_descriptor = {
+static uint16_t ftrn_profile_uuids[] = {
 	SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+	SDP_UUID_PROTOCOL_OBEX,
+};
+
+profile_t	ftrn_profile_descriptor = {
+	ftrn_profile_uuids,
+	sizeof(ftrn_profile_uuids),
 	sizeof(sdp_ftrn_profile_t),
 	common_profile_server_channel_valid,
 	(attr_t const * const) &ftrn_profile_attrs
--- /usr/src/usr.sbin/sdpd/hf.c	2006-08-17 21:13:31.000000000 +0100
+++ hf.c	2007-11-06 09:27:12.000000000 +0000
@@ -148,8 +148,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	hf_profile_descriptor = {
+static uint16_t	hf_profile_uuids[] = {
 	SDP_SERVICE_CLASS_HANDSFREE,
+	SDP_SERVICE_CLASS_GENERIC_AUDIO,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+};
+
+profile_t	hf_profile_descriptor = {
+	hf_profile_uuids,
+	sizeof(hf_profile_uuids),
 	sizeof(sdp_hf_profile_t),
 	hf_profile_data_valid,
 	(attr_t const * const) &hf_profile_attrs
--- /usr/src/usr.sbin/sdpd/hset.c	2006-06-19 16:44:56.000000000 +0100
+++ hset.c	2007-11-06 09:27:16.000000000 +0000
@@ -128,8 +128,17 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	hset_profile_descriptor = {
+static uint16_t hset_profile_uuids[] = {
 	SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY,
+	SDP_SERVICE_CLASS_GENERIC_AUDIO,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+	SDP_SERVICE_CLASS_HEADSET,
+};
+
+profile_t	hset_profile_descriptor = {
+	hset_profile_uuids,
+	sizeof(hset_profile_uuids),
 	sizeof(sdp_hset_profile_t),
 	hset_profile_data_valid,
 	(attr_t const * const) &hset_profile_attrs
--- /usr/src/usr.sbin/sdpd/irmc.c	2006-06-19 16:44:56.000000000 +0100
+++ irmc.c	2007-11-06 09:27:19.000000000 +0000
@@ -129,8 +129,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	irmc_profile_descriptor = {
+static uint16_t irmc_profile_uuids[] = {
 	SDP_SERVICE_CLASS_IR_MC_SYNC,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+	SDP_UUID_PROTOCOL_OBEX,
+};
+
+profile_t	irmc_profile_descriptor = {
+	irmc_profile_uuids,
+	sizeof(irmc_profile_uuids),
 	sizeof(sdp_irmc_profile_t),
 	obex_profile_data_valid,
 	(attr_t const * const) &irmc_profile_attrs
--- /usr/src/usr.sbin/sdpd/irmc_command.c	2006-06-19 16:44:56.000000000 +0100
+++ irmc_command.c	2007-11-06 09:27:23.000000000 +0000
@@ -113,8 +113,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	irmc_command_profile_descriptor = {
+static uint16_t	irmc_command_profile_uuids[] = {
 	SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+	SDP_UUID_PROTOCOL_OBEX,
+};
+
+profile_t	irmc_command_profile_descriptor = {
+	irmc_command_profile_uuids,
+	sizeof(irmc_command_profile_uuids),
 	sizeof(sdp_irmc_command_profile_t),
 	common_profile_server_channel_valid,
 	(attr_t const * const) &irmc_command_profile_attrs
--- /usr/src/usr.sbin/sdpd/lan.c	2006-06-19 16:44:56.000000000 +0100
+++ lan.c	2007-11-06 09:27:27.000000000 +0000
@@ -173,8 +173,15 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	lan_profile_descriptor = {
+static uint16_t lan_profile_uuids[] = {
 	SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+};
+
+profile_t	lan_profile_descriptor = {
+	lan_profile_uuids,
+	sizeof(lan_profile_uuids),
 	sizeof(sdp_lan_profile_t),
 	lan_profile_data_valid,
 	(attr_t const * const) &lan_profile_attrs
--- /usr/src/usr.sbin/sdpd/opush.c	2006-06-19 16:44:56.000000000 +0100
+++ opush.c	2007-11-06 09:27:32.000000000 +0000
@@ -129,8 +129,16 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	opush_profile_descriptor = {
+static uint16_t opush_profile_uuids[] = {
 	SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+	SDP_UUID_PROTOCOL_OBEX,
+};
+
+profile_t	opush_profile_descriptor = {
+	opush_profile_uuids,
+	sizeof(opush_profile_uuids),
 	sizeof(sdp_opush_profile_t),
 	obex_profile_data_valid,
 	(attr_t const * const) &opush_profile_attrs
--- /usr/src/usr.sbin/sdpd/profile.c	2006-08-19 18:11:04.000000000 +0100
+++ profile.c	2007-11-06 09:58:54.000000000 +0000
@@ -74,7 +74,7 @@
 	int32_t			i;
 
 	for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++)
-		if (profiles[i]->uuid == uuid)
+		if (profiles[i]->uuid[0] == uuid)
 			return (profiles[i]);
 
 	return (NULL);
--- /usr/src/usr.sbin/sdpd/profile.h	2006-06-19 16:44:56.000000000 +0100
+++ profile.h	2007-11-06 09:39:13.000000000 +0000
@@ -63,7 +63,8 @@
 
 struct profile
 {
-	uint16_t		uuid;	/* profile uuid */
+	uint16_t *		uuid;	/* profile uuid list */
+	ssize_t			usize;	/* profile uuid list size */
 	uint16_t		dsize;	/* profile data size */
 	profile_data_valid_p	valid;	/* profile data validator */
 	attr_t const * const	attrs;	/* supported attributes */
--- /usr/src/usr.sbin/sdpd/provider.c	2006-06-19 16:44:56.000000000 +0100
+++ provider.c	2007-11-06 10:31:52.000000000 +0000
@@ -36,10 +36,12 @@
 
 #include <sys/queue.h>
 #include <bluetooth.h>
+#include <sdp.h>
 #include <string.h>
 #include <stdlib.h>
 #include "profile.h"
 #include "provider.h"
+#include "uuid-private.h"
 
 static TAILQ_HEAD(, provider)	providers = TAILQ_HEAD_INITIALIZER(providers);
 static uint32_t			change_state = 0;
@@ -198,3 +200,38 @@
 {
 	return (change_state);
 }
+
+/*
+ * Match provider to UUID list
+ *
+ *	all UUIDs in list must match one of the
+ *	provider UUIDs or the PublicBrowseGroup
+ */
+
+int
+provider_match_uuid(provider_p provider, uint128_t *uuid, int ucount)
+{
+	uint128_t puuid;
+	int num, max;
+
+	max = provider->profile->usize / sizeof(provider->profile->uuid[0]);
+
+	for (; ucount-- > 0 ; uuid++) {
+		if (memcmp(uuid, &uuid_public_browse_group, sizeof(*uuid)) == 0)
+			continue;
+
+		for (num = 0 ; ; num++) {
+			if (num == max)
+				return 0;
+
+			memcpy(&puuid, &uuid_base, sizeof(puuid));
+			puuid.b[2] = provider->profile->uuid[num] >> 8;
+			puuid.b[3] = provider->profile->uuid[num];
+
+			if (memcmp(uuid, &puuid, sizeof(*uuid)) == 0)
+				break;
+		}
+	}
+
+	return 1;
+}
--- /usr/src/usr.sbin/sdpd/provider.h	2006-06-19 16:44:56.000000000 +0100
+++ provider.h	2007-11-06 09:51:59.000000000 +0000
@@ -101,6 +101,9 @@
 provider_p	provider_get_next		(provider_p provider);
 uint32_t	provider_get_change_state	(void);
 
+int		provider_match_uuid		(provider_p provider,
+						 uint128_t *ulist, int ucount);
+
 int32_t server_prepare_attr_list(provider_p const, uint8_t const *, uint8_t const *,
 		uint8_t *, uint8_t const *);
 
--- /usr/src/usr.sbin/sdpd/sd.c	2006-06-19 16:44:56.000000000 +0100
+++ sd.c	2007-11-06 09:27:47.000000000 +0000
@@ -208,8 +208,14 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	sd_profile_descriptor = {
+static uint16_t sd_profile_uuids[] = {
 	SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER,
+	SDP_UUID_PROTOCOL_L2CAP,
+};
+
+profile_t	sd_profile_descriptor = {
+	sd_profile_uuids,
+	sizeof(sd_profile_uuids),
 	0,
 	(profile_data_valid_p) NULL,
 	(attr_t const * const) &sd_profile_attrs
--- /usr/src/usr.sbin/sdpd/server.h	2007-03-18 12:11:13.000000000 +0000
+++ server.h	2007-11-05 10:40:53.000000000 +0000
@@ -109,6 +109,8 @@
 void	server_shutdown(server_p srv);
 int32_t	server_do(server_p srv);
 
+int	server_get_service_search_pattern(uint8_t const **buf, uint8_t const *end, uint128_t *uuid);
+
 int32_t	server_prepare_service_search_response(server_p srv, int32_t fd);
 int32_t	server_send_service_search_response(server_p srv, int32_t fd);
 
--- /usr/src/usr.sbin/sdpd/sp.c	2006-06-19 16:44:56.000000000 +0100
+++ sp.c	2007-11-06 09:27:50.000000000 +0000
@@ -113,8 +113,15 @@
 	{ 0, NULL } /* end entry */
 };
 
-profile_t	sp_profile_descriptor = {
+static uint16_t sp_profile_uuids[] = {
 	SDP_SERVICE_CLASS_SERIAL_PORT,
+	SDP_UUID_PROTOCOL_L2CAP,
+	SDP_UUID_PROTOCOL_RFCOMM,
+};
+
+profile_t	sp_profile_descriptor = {
+	sp_profile_uuids,
+	sizeof(sp_profile_uuids),
 	sizeof(sdp_sp_profile_t),
 	common_profile_server_channel_valid,
 	(attr_t const * const) &sp_profile_attrs
--- /usr/src/usr.sbin/sdpd/ssar.c	2006-06-19 16:44:56.000000000 +0100
+++ ssar.c	2007-11-06 10:39:35.000000000 +0000
@@ -55,12 +55,11 @@
 	uint8_t		*rsp = srv->fdidx[fd].rsp;
 	uint8_t const	*rsp_end = rsp + L2CAP_MTU_MAXIMUM;
 
-	uint8_t const	*sspptr = NULL, *aidptr = NULL;
-	uint8_t		*ptr = NULL;
+	uint8_t const	*aidptr = NULL;
 
 	provider_t	*provider = NULL;
-	int32_t		 type, rsp_limit, ssplen, aidlen, cslen, cs;
-	uint128_t	 uuid, puuid;
+	int32_t		 type, rsp_limit, ucount, aidlen, cslen, cs;
+	uint128_t	 ulist[12];
 
 	/*
 	 * Minimal Service Search Attribute Request request
@@ -73,31 +72,11 @@
 	 * value8		- 1 byte  ContinuationState
 	 */
 
-	if (req_end - req < 13)
-		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-	/* Get size of ServiceSearchPattern */
-	ssplen = 0;
-	SDP_GET8(type, req);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(ssplen, req);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(ssplen, req);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(ssplen, req);
-		break;
-	}
-	if (ssplen <= 0)
+	/* Get ServiceSearchPattern */
+	ucount = server_get_service_search_pattern(&req, req_end, ulist);
+	if (ucount < 1 || ucount > 12)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
-	sspptr = req;
-	req += ssplen;
-
 	/* Get MaximumAttributeByteCount */
 	if (req + 2 > req_end)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
@@ -145,13 +124,12 @@
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
 	SDP_GET8(cslen, req);
-	if (cslen != 0) {
-		if (cslen != 2 || req_end - req != 2)
-			return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
+	if (cslen == 2 && req + 2 == req_end)
 		SDP_GET16(cs, req);
-	} else
+	else if (cslen == 0 && req == req_end)
 		cs = 0;
+	else
+		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
 	/* Process the request. First, check continuation state */
 	if (srv->fdidx[fd].rsp_cs != cs)
@@ -168,70 +146,23 @@
 	 *	[ attr list ]
 	 */
 
-	ptr = rsp + 3;
-
-	while (ssplen > 0) {
-		SDP_GET8(type, sspptr);
-		ssplen --;
-
-		switch (type) {
-		case SDP_DATA_UUID16:
-			if (ssplen < 2)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-			memcpy(&uuid, &uuid_base, sizeof(uuid));
-			uuid.b[2] = *sspptr ++;
-			uuid.b[3] = *sspptr ++;
-			ssplen -= 2;
-			break;
-
-		case SDP_DATA_UUID32:
-			if (ssplen < 4)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-			memcpy(&uuid, &uuid_base, sizeof(uuid));
-			uuid.b[0] = *sspptr ++;
-			uuid.b[1] = *sspptr ++;
-			uuid.b[2] = *sspptr ++;
-			uuid.b[3] = *sspptr ++;
-			ssplen -= 4;
-			break;
-
-		case SDP_DATA_UUID128:
-			if (ssplen < 16)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-			memcpy(uuid.b, sspptr, 16);
-			sspptr += 16;
-			ssplen -= 16;
-			break;
-
-		default:
-			return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-			/* NOT REACHED */
-		}
-
-		for (provider = provider_get_first();
-		     provider != NULL;
-		     provider = provider_get_next(provider)) {
-			if (!provider_match_bdaddr(provider, &srv->req_sa.bt_bdaddr))
-				continue;
+	rsp += 3;	/* leave space for sequence header */
 
-			memcpy(&puuid, &uuid_base, sizeof(puuid));
-			puuid.b[2] = provider->profile->uuid >> 8;
-			puuid.b[3] = provider->profile->uuid;
+	for (provider = provider_get_first();
+	     provider != NULL;
+	     provider = provider_get_next(provider)) {
+		if (!provider_match_bdaddr(provider, &srv->req_sa.bt_bdaddr))
+			continue;
 
-			if (memcmp(&uuid, &puuid, sizeof(uuid)) != 0 &&
-			    memcmp(&uuid, &uuid_public_browse_group, sizeof(uuid)) != 0)
-				continue;
+		if (!provider_match_uuid(provider, ulist, ucount))
+			continue;
 
-			cs = server_prepare_attr_list(provider,
-				aidptr, aidptr + aidlen, ptr, rsp_end);
-			if (cs < 0)
-				return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES);
+		cs = server_prepare_attr_list(provider,
+			aidptr, aidptr + aidlen, rsp, rsp_end);
+		if (cs < 0)
+			return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES);
 
-			ptr += cs;
-		}
+		rsp += cs;
 	}
 
 	/* Set reply size (not counting PDU header and continuation state) */
@@ -239,13 +170,13 @@
 	if (srv->fdidx[fd].rsp_limit > rsp_limit)
 		srv->fdidx[fd].rsp_limit = rsp_limit;
 
-	srv->fdidx[fd].rsp_size = ptr - rsp;
+	srv->fdidx[fd].rsp_size = rsp - srv->fdidx[fd].rsp;
 	srv->fdidx[fd].rsp_cs = 0;
 
 	/* Fix AttributeLists sequence header */
-	ptr = rsp;
-	SDP_PUT8(SDP_DATA_SEQ16, ptr);
-	SDP_PUT16(srv->fdidx[fd].rsp_size - 3, ptr);
+	rsp = srv->fdidx[fd].rsp;
+	SDP_PUT8(SDP_DATA_SEQ16, rsp);
+	SDP_PUT16(srv->fdidx[fd].rsp_size - 3, rsp);
 
 	return (0);
 }
--- /usr/src/usr.sbin/sdpd/ssr.c	2006-06-19 16:44:56.000000000 +0100
+++ ssr.c	2007-11-06 10:49:46.000000000 +0000
@@ -49,21 +49,118 @@
 #include "uuid-private.h"
 
 /*
+ * Extract ServiceSearchPattern from request to uuid array
+ *	return count or 0 if error
+ */
+int
+server_get_service_search_pattern(uint8_t const **buf, uint8_t const *end, uint128_t *uuid)
+{
+	uint8_t const *req = *buf;
+	uint32_t type, ssplen;
+	int count;
+
+	if (req + 1 > end)
+		return 0;
+
+	SDP_GET8(type, req);
+
+	ssplen = 0;
+	switch (type) {
+	case SDP_DATA_SEQ8:
+		if (req + 1 > end)
+			return 0;
+
+		SDP_GET8(ssplen, req);
+		break;
+
+	case SDP_DATA_SEQ16:
+		if (req + 2 > end)
+			return 0;
+
+		SDP_GET16(ssplen, req);
+		break;
+
+	case SDP_DATA_SEQ32:
+		if (req + 4 > end)
+			return 0;
+
+		SDP_GET32(ssplen, req);
+		break;
+
+	default:
+		return 0;
+	}
+
+	if (req + ssplen > end)
+		return 0;
+
+	count = 0;
+	while (ssplen > 0) {
+		if (count == 12)
+			return 0;
+
+		SDP_GET8(type, req);
+		ssplen--;
+
+		switch (type) {
+		case SDP_DATA_UUID16:
+			if (ssplen < 2)
+				return 0;
+
+			memcpy(uuid, &uuid_base, sizeof(*uuid));
+			uuid->b[2] = *req++;
+			uuid->b[3] = *req++;
+			ssplen -= 2;
+			break;
+
+		case SDP_DATA_UUID32:
+			if (ssplen < 4)
+				return 0;
+
+			memcpy(uuid, &uuid_base, sizeof(*uuid));
+			uuid->b[0] = *req++;
+			uuid->b[1] = *req++;
+			uuid->b[2] = *req++;
+			uuid->b[3] = *req++;
+			ssplen -= 4;
+			break;
+
+		case SDP_DATA_UUID128:
+			if (ssplen < 16)
+				return 0;
+
+			memcpy(uuid, req, 16);
+			req += 16;
+			ssplen -= 16;
+			break;
+
+		default:
+			return 0;
+		}
+
+		count++;
+		uuid++;
+	}
+
+	*buf = req;
+	return count;
+}
+
+/*
  * Prepare SDP Service Search Response
  */
 
 int32_t
 server_prepare_service_search_response(server_p srv, int32_t fd)
 {
-	uint8_t 	*req = srv->req + sizeof(sdp_pdu_t);
+	uint8_t const	*req = srv->req + sizeof(sdp_pdu_t);
 	uint8_t const	*req_end = req + ((sdp_pdu_p)(srv->req))->len;
 	uint8_t		*rsp = srv->fdidx[fd].rsp;
 	uint8_t const	*rsp_end = rsp + L2CAP_MTU_MAXIMUM;
 
-	uint8_t		*ptr = NULL;
 	provider_t	*provider = NULL;
-	int32_t		 type, ssplen, rsp_limit, rcount, cslen, cs;
-	uint128_t	 uuid, puuid;
+	int32_t		 ucount, rsp_limit, cslen, cs;
+	uint128_t	 ulist[12];
 
 	/*
 	 * Minimal SDP Service Search Request
@@ -74,50 +171,30 @@
 	 * value8		- 1 byte  ContinuationState
 	 */
 
-	if (req_end - req < 8)
-		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-	/* Get size of ServiceSearchPattern */
-	ssplen = 0;
-	SDP_GET8(type, req);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(ssplen, req);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(ssplen, req);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(ssplen, req);
-		break;
-	}
-	if (ssplen <= 0)
+	/* Get ServiceSearchPattern into uuid array */
+	ucount = server_get_service_search_pattern(&req, req_end, ulist);
+	if (ucount < 1 || ucount > 12)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
-	ptr = (uint8_t *) req + ssplen;
-
 	/* Get MaximumServiceRecordCount */
-	if (ptr + 2 > req_end)
+	if (req + 2 > req_end)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
-	SDP_GET16(rsp_limit, ptr);
+	SDP_GET16(rsp_limit, req);
 	if (rsp_limit <= 0)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
 	/* Get ContinuationState */
-	if (ptr + 1 > req_end)
+	if (req + 1 > req_end)
 		return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
 
-	SDP_GET8(cslen, ptr);
-	if (cslen != 0) {
-		if (cslen != 2 || req_end - ptr != 2)
-			return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-		SDP_GET16(cs, ptr);
-	} else
+	SDP_GET8(cslen, req);
+	if (cslen == 2 && req + 2 == req_end)
+		SDP_GET16(cs, req);
+	else if (cslen == 0 && req == req_end)
 		cs = 0;
+	else
+		return (SDP_ERROR_CODE_INVALID_CONTINUATION_STATE);
 
 	/* Process the request. First, check continuation state */
 	if (srv->fdidx[fd].rsp_cs != cs)
@@ -132,79 +209,27 @@
 	 * value16	- 2 bytes CurrentServiceRecordCount (not incl.)
 	 * value32	- 4 bytes handle
 	 * [ value32 ]
-	 *
-	 * Calculate how many record handles we can fit
-	 * in our reply buffer and adjust rlimit.
 	 */
 
-	ptr = rsp;
-	rcount = (rsp_end - ptr) / 4;
-	if (rcount < rsp_limit)
-		rsp_limit = rcount;
-
-	/* Look for the record handles */
-	for (rcount = 0; ssplen > 0 && rcount < rsp_limit; ) {
-		SDP_GET8(type, req);
-		ssplen --;
-
-		switch (type) {
-		case SDP_DATA_UUID16:
-			if (ssplen < 2)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-			memcpy(&uuid, &uuid_base, sizeof(uuid));
-			uuid.b[2] = *req ++;
-			uuid.b[3] = *req ++;
-			ssplen -= 2;
-			break;
-
-		case SDP_DATA_UUID32:
-			if (ssplen < 4)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-
-			memcpy(&uuid, &uuid_base, sizeof(uuid));
-			uuid.b[0] = *req ++;
-			uuid.b[1] = *req ++;
-			uuid.b[2] = *req ++;
-			uuid.b[3] = *req ++;
-			ssplen -= 4;
-			break;
+	/* Look for the record handles and add to the rsp buffer */
+	for (provider = provider_get_first();
+	     provider != NULL;
+	     provider = provider_get_next(provider)) {
+		if (!provider_match_bdaddr(provider, &srv->req_sa.bt_bdaddr))
+			continue;
 
-		case SDP_DATA_UUID128:
-			if (ssplen < 16)
-				return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
+		if (!provider_match_uuid(provider, ulist, ucount))
+			continue;
 
-			memcpy(uuid.b, req, 16);
-			req += 16;
-			ssplen -= 16;
+		if (rsp + 4 > rsp_end)
 			break;
 
-		default:
-			return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
-			/* NOT REACHED */
-		}
-
-		for (provider = provider_get_first();
-		     provider != NULL && rcount < rsp_limit;
-		     provider = provider_get_next(provider)) {
-			if (!provider_match_bdaddr(provider, &srv->req_sa.bt_bdaddr))
-				continue;
-
-			memcpy(&puuid, &uuid_base, sizeof(puuid));
-			puuid.b[2] = provider->profile->uuid >> 8;
-			puuid.b[3] = provider->profile->uuid;
-
-			if (memcmp(&uuid, &puuid, sizeof(uuid)) == 0 ||
-			    memcmp(&uuid, &uuid_public_browse_group, sizeof(uuid)) == 0) {
-				SDP_PUT32(provider->handle, ptr);
-				rcount ++;
-			}
-		}
+		SDP_PUT32(provider->handle, rsp);
 	}
 
 	/* Set reply size (not counting PDU header and continuation state) */
 	srv->fdidx[fd].rsp_limit = srv->fdidx[fd].omtu - sizeof(sdp_pdu_t) - 4;
-	srv->fdidx[fd].rsp_size = ptr - rsp;
+	srv->fdidx[fd].rsp_size = rsp - srv->fdidx[fd].rsp;
 	srv->fdidx[fd].rsp_cs = 0;
 
 	return (0);

[-- Attachment #3 --]
#include <bluetooth.h>
#include <err.h>
#include <errno.h>
#include <sdp.h>
#include <stdlib.h>

uint16_t services[] = {
	SDP_UUID_PROTOCOL_OBEX,
	//SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH,
};

uint32_t attrs[] = {
	SDP_ATTR_RANGE(	SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
			SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
	SDP_ATTR_RANGE( SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS,
			SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS),
	SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST,
			SDP_ATTR_SERVICE_CLASS_ID_LIST),
};

#define NUM(v)	(sizeof(v) / sizeof(v[0]))

sdp_attr_t values[8];
uint8_t buffer[NUM(values)][512];

int
main(int ac, char *av[])
{
	void *ss;
	int i, j, rv;

	for (i = 0 ; i < NUM(values) ; i++) {
		values[i].flags = SDP_ATTR_INVALID;
		values[i].attr = 0;
		values[i].vlen = sizeof(buffer[i]);
		values[i].value = buffer[i];
	}

	ss = sdp_open_local(NULL);
	if (ss == NULL || (errno = sdp_error(ss)) != 0)
		err(EXIT_FAILURE, "sdp_open_local");

	rv = sdp_search(ss, NUM(services), services,
			    NUM(attrs), attrs,
			    NUM(values), values);
			
	if (rv != 0)
		errx(EXIT_FAILURE, "sdp_search: %s", strerror(rv));

	sdp_close(ss);

	for (i = 0 ; i < NUM(values) ; i++) {
		printf("value %d:\n", i);
		if (values[i].flags != SDP_ATTR_OK)
			continue;

		printf("\tattr  %04x\n", values[i].attr);
		printf("\tvalue");
		for (j = 0 ; j < values[i].vlen ; j++)
			printf(" %02x", values[i].value[j]);

		printf("\n");
	}

	return EXIT_SUCCESS;
}
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E1IpN5T-0006Rs-Jv>