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>
