11de7b4b8SPedro F. Giffuni /*-
207be7a6cSMaksim Yevmenkin * ssar.c
307be7a6cSMaksim Yevmenkin *
4*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni *
607be7a6cSMaksim Yevmenkin * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
707be7a6cSMaksim Yevmenkin * All rights reserved.
807be7a6cSMaksim Yevmenkin *
907be7a6cSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without
1007be7a6cSMaksim Yevmenkin * modification, are permitted provided that the following conditions
1107be7a6cSMaksim Yevmenkin * are met:
1207be7a6cSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright
1307be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer.
1407be7a6cSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright
1507be7a6cSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the
1607be7a6cSMaksim Yevmenkin * documentation and/or other materials provided with the distribution.
1707be7a6cSMaksim Yevmenkin *
1807be7a6cSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1907be7a6cSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2007be7a6cSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2107be7a6cSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2207be7a6cSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2307be7a6cSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2407be7a6cSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2507be7a6cSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2607be7a6cSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2707be7a6cSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2807be7a6cSMaksim Yevmenkin * SUCH DAMAGE.
2907be7a6cSMaksim Yevmenkin *
3007be7a6cSMaksim Yevmenkin * $Id: ssar.c,v 1.4 2004/01/12 22:54:31 max Exp $
3107be7a6cSMaksim Yevmenkin */
3207be7a6cSMaksim Yevmenkin
3307be7a6cSMaksim Yevmenkin #include <sys/queue.h>
348d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
3507be7a6cSMaksim Yevmenkin #include <bluetooth.h>
3607be7a6cSMaksim Yevmenkin #include <sdp.h>
3707be7a6cSMaksim Yevmenkin #include <string.h>
3807be7a6cSMaksim Yevmenkin #include "profile.h"
3907be7a6cSMaksim Yevmenkin #include "provider.h"
4007be7a6cSMaksim Yevmenkin #include "server.h"
41ee935b58SMaksim Yevmenkin #include "uuid-private.h"
4207be7a6cSMaksim Yevmenkin
4307be7a6cSMaksim Yevmenkin /* from sar.c */
4407be7a6cSMaksim Yevmenkin int32_t server_prepare_attr_list(provider_p const provider,
4507be7a6cSMaksim Yevmenkin uint8_t const *req, uint8_t const * const req_end,
4607be7a6cSMaksim Yevmenkin uint8_t *rsp, uint8_t const * const rsp_end);
4707be7a6cSMaksim Yevmenkin
4807be7a6cSMaksim Yevmenkin /*
492d3a84f5SHans Petter Selasky * Scan an attribute for matching UUID.
502d3a84f5SHans Petter Selasky */
512d3a84f5SHans Petter Selasky static int
server_search_uuid_sub(uint8_t * buf,uint8_t const * const eob,const uint128_t * uuid)522d3a84f5SHans Petter Selasky server_search_uuid_sub(uint8_t *buf, uint8_t const * const eob, const uint128_t *uuid)
532d3a84f5SHans Petter Selasky {
542d3a84f5SHans Petter Selasky int128_t duuid;
552d3a84f5SHans Petter Selasky uint32_t value;
562d3a84f5SHans Petter Selasky uint8_t type;
572d3a84f5SHans Petter Selasky
582d3a84f5SHans Petter Selasky while (buf < eob) {
592d3a84f5SHans Petter Selasky
602d3a84f5SHans Petter Selasky SDP_GET8(type, buf);
612d3a84f5SHans Petter Selasky
622d3a84f5SHans Petter Selasky switch (type) {
632d3a84f5SHans Petter Selasky case SDP_DATA_UUID16:
642d3a84f5SHans Petter Selasky if (buf + 2 > eob)
652d3a84f5SHans Petter Selasky continue;
662d3a84f5SHans Petter Selasky SDP_GET16(value, buf);
672d3a84f5SHans Petter Selasky
682d3a84f5SHans Petter Selasky memcpy(&duuid, &uuid_base, sizeof(duuid));
692d3a84f5SHans Petter Selasky duuid.b[2] = value >> 8 & 0xff;
702d3a84f5SHans Petter Selasky duuid.b[3] = value & 0xff;
712d3a84f5SHans Petter Selasky
722d3a84f5SHans Petter Selasky if (memcmp(&duuid, uuid, sizeof(duuid)) == 0)
732d3a84f5SHans Petter Selasky return (0);
742d3a84f5SHans Petter Selasky break;
752d3a84f5SHans Petter Selasky case SDP_DATA_UUID32:
762d3a84f5SHans Petter Selasky if (buf + 4 > eob)
772d3a84f5SHans Petter Selasky continue;
782d3a84f5SHans Petter Selasky SDP_GET32(value, buf);
792d3a84f5SHans Petter Selasky memcpy(&duuid, &uuid_base, sizeof(duuid));
802d3a84f5SHans Petter Selasky duuid.b[0] = value >> 24 & 0xff;
812d3a84f5SHans Petter Selasky duuid.b[1] = value >> 16 & 0xff;
822d3a84f5SHans Petter Selasky duuid.b[2] = value >> 8 & 0xff;
832d3a84f5SHans Petter Selasky duuid.b[3] = value & 0xff;
842d3a84f5SHans Petter Selasky
852d3a84f5SHans Petter Selasky if (memcmp(&duuid, uuid, sizeof(duuid)) == 0)
862d3a84f5SHans Petter Selasky return (0);
872d3a84f5SHans Petter Selasky break;
882d3a84f5SHans Petter Selasky case SDP_DATA_UUID128:
892d3a84f5SHans Petter Selasky if (buf + 16 > eob)
902d3a84f5SHans Petter Selasky continue;
912d3a84f5SHans Petter Selasky SDP_GET_UUID128(&duuid, buf);
922d3a84f5SHans Petter Selasky
932d3a84f5SHans Petter Selasky if (memcmp(&duuid, uuid, sizeof(duuid)) == 0)
942d3a84f5SHans Petter Selasky return (0);
952d3a84f5SHans Petter Selasky break;
962d3a84f5SHans Petter Selasky case SDP_DATA_UINT8:
972d3a84f5SHans Petter Selasky case SDP_DATA_INT8:
982d3a84f5SHans Petter Selasky case SDP_DATA_SEQ8:
992d3a84f5SHans Petter Selasky buf++;
1002d3a84f5SHans Petter Selasky break;
1012d3a84f5SHans Petter Selasky case SDP_DATA_UINT16:
1022d3a84f5SHans Petter Selasky case SDP_DATA_INT16:
1032d3a84f5SHans Petter Selasky case SDP_DATA_SEQ16:
1042d3a84f5SHans Petter Selasky buf += 2;
1052d3a84f5SHans Petter Selasky break;
1062d3a84f5SHans Petter Selasky case SDP_DATA_UINT32:
1072d3a84f5SHans Petter Selasky case SDP_DATA_INT32:
1082d3a84f5SHans Petter Selasky case SDP_DATA_SEQ32:
1092d3a84f5SHans Petter Selasky buf += 4;
1102d3a84f5SHans Petter Selasky break;
1112d3a84f5SHans Petter Selasky case SDP_DATA_UINT64:
1122d3a84f5SHans Petter Selasky case SDP_DATA_INT64:
1132d3a84f5SHans Petter Selasky buf += 8;
1142d3a84f5SHans Petter Selasky break;
1152d3a84f5SHans Petter Selasky case SDP_DATA_UINT128:
1162d3a84f5SHans Petter Selasky case SDP_DATA_INT128:
1172d3a84f5SHans Petter Selasky buf += 16;
1182d3a84f5SHans Petter Selasky break;
1192d3a84f5SHans Petter Selasky case SDP_DATA_STR8:
1202d3a84f5SHans Petter Selasky if (buf + 1 > eob)
1212d3a84f5SHans Petter Selasky continue;
1222d3a84f5SHans Petter Selasky SDP_GET8(value, buf);
1232d3a84f5SHans Petter Selasky buf += value;
1242d3a84f5SHans Petter Selasky break;
1252d3a84f5SHans Petter Selasky case SDP_DATA_STR16:
1262d3a84f5SHans Petter Selasky if (buf + 2 > eob)
1272d3a84f5SHans Petter Selasky continue;
1282d3a84f5SHans Petter Selasky SDP_GET16(value, buf);
1292d3a84f5SHans Petter Selasky if (value > (eob - buf))
1302d3a84f5SHans Petter Selasky return (1);
1312d3a84f5SHans Petter Selasky buf += value;
1322d3a84f5SHans Petter Selasky break;
1332d3a84f5SHans Petter Selasky case SDP_DATA_STR32:
1342d3a84f5SHans Petter Selasky if (buf + 4 > eob)
1352d3a84f5SHans Petter Selasky continue;
1362d3a84f5SHans Petter Selasky SDP_GET32(value, buf);
1372d3a84f5SHans Petter Selasky if (value > (eob - buf))
1382d3a84f5SHans Petter Selasky return (1);
1392d3a84f5SHans Petter Selasky buf += value;
1402d3a84f5SHans Petter Selasky break;
1412d3a84f5SHans Petter Selasky case SDP_DATA_BOOL:
1422d3a84f5SHans Petter Selasky buf += 1;
1432d3a84f5SHans Petter Selasky break;
1442d3a84f5SHans Petter Selasky default:
1452d3a84f5SHans Petter Selasky return (1);
1462d3a84f5SHans Petter Selasky }
1472d3a84f5SHans Petter Selasky }
1482d3a84f5SHans Petter Selasky return (1);
1492d3a84f5SHans Petter Selasky }
1502d3a84f5SHans Petter Selasky
1512d3a84f5SHans Petter Selasky /*
1522d3a84f5SHans Petter Selasky * Search a provider for matching UUID in its attributes.
1532d3a84f5SHans Petter Selasky */
1542d3a84f5SHans Petter Selasky static int
server_search_uuid(provider_p const provider,const uint128_t * uuid)1552d3a84f5SHans Petter Selasky server_search_uuid(provider_p const provider, const uint128_t *uuid)
1562d3a84f5SHans Petter Selasky {
1572d3a84f5SHans Petter Selasky uint8_t buffer[256];
1582d3a84f5SHans Petter Selasky const attr_t *attr;
1592d3a84f5SHans Petter Selasky int len;
1602d3a84f5SHans Petter Selasky
1612d3a84f5SHans Petter Selasky for (attr = provider->profile->attrs; attr->create != NULL; attr++) {
1622d3a84f5SHans Petter Selasky
1632d3a84f5SHans Petter Selasky len = attr->create(buffer, buffer + sizeof(buffer),
1642d3a84f5SHans Petter Selasky (const uint8_t *)provider->profile, sizeof(*provider->profile));
1652d3a84f5SHans Petter Selasky if (len < 0)
1662d3a84f5SHans Petter Selasky continue;
1672d3a84f5SHans Petter Selasky if (server_search_uuid_sub(buffer, buffer + len, uuid) == 0)
1682d3a84f5SHans Petter Selasky return (0);
1692d3a84f5SHans Petter Selasky }
1702d3a84f5SHans Petter Selasky return (1);
1712d3a84f5SHans Petter Selasky }
1722d3a84f5SHans Petter Selasky
1732d3a84f5SHans Petter Selasky /*
17407be7a6cSMaksim Yevmenkin * Prepare SDP Service Search Attribute Response
17507be7a6cSMaksim Yevmenkin */
17607be7a6cSMaksim Yevmenkin
17707be7a6cSMaksim Yevmenkin int32_t
server_prepare_service_search_attribute_response(server_p srv,int32_t fd)17807be7a6cSMaksim Yevmenkin server_prepare_service_search_attribute_response(server_p srv, int32_t fd)
17907be7a6cSMaksim Yevmenkin {
18007be7a6cSMaksim Yevmenkin uint8_t const *req = srv->req + sizeof(sdp_pdu_t);
18107be7a6cSMaksim Yevmenkin uint8_t const *req_end = req + ((sdp_pdu_p)(srv->req))->len;
18207be7a6cSMaksim Yevmenkin uint8_t *rsp = srv->fdidx[fd].rsp;
18307be7a6cSMaksim Yevmenkin uint8_t const *rsp_end = rsp + NG_L2CAP_MTU_MAXIMUM;
18407be7a6cSMaksim Yevmenkin
18507be7a6cSMaksim Yevmenkin uint8_t const *sspptr = NULL, *aidptr = NULL;
18607be7a6cSMaksim Yevmenkin uint8_t *ptr = NULL;
18707be7a6cSMaksim Yevmenkin
18807be7a6cSMaksim Yevmenkin provider_t *provider = NULL;
189ee935b58SMaksim Yevmenkin int32_t type, rsp_limit, ssplen, aidlen, cslen, cs;
190ee935b58SMaksim Yevmenkin uint128_t uuid, puuid;
19107be7a6cSMaksim Yevmenkin
19207be7a6cSMaksim Yevmenkin /*
19307be7a6cSMaksim Yevmenkin * Minimal Service Search Attribute Request request
19407be7a6cSMaksim Yevmenkin *
19507be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
19607be7a6cSMaksim Yevmenkin * uuid16 value16 - 3 bytes ServiceSearchPattern
19707be7a6cSMaksim Yevmenkin * value16 - 2 bytes MaximumAttributeByteCount
19807be7a6cSMaksim Yevmenkin * seq8 len8 - 2 bytes
19907be7a6cSMaksim Yevmenkin * uint16 value16 - 3 bytes AttributeIDList
20007be7a6cSMaksim Yevmenkin * value8 - 1 byte ContinuationState
20107be7a6cSMaksim Yevmenkin */
20207be7a6cSMaksim Yevmenkin
20307be7a6cSMaksim Yevmenkin if (req_end - req < 13)
20407be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
20507be7a6cSMaksim Yevmenkin
20607be7a6cSMaksim Yevmenkin /* Get size of ServiceSearchPattern */
20707be7a6cSMaksim Yevmenkin ssplen = 0;
20807be7a6cSMaksim Yevmenkin SDP_GET8(type, req);
20907be7a6cSMaksim Yevmenkin switch (type) {
21007be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ8:
21107be7a6cSMaksim Yevmenkin SDP_GET8(ssplen, req);
21207be7a6cSMaksim Yevmenkin break;
21307be7a6cSMaksim Yevmenkin
21407be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ16:
21507be7a6cSMaksim Yevmenkin SDP_GET16(ssplen, req);
21607be7a6cSMaksim Yevmenkin break;
21707be7a6cSMaksim Yevmenkin
21807be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ32:
21907be7a6cSMaksim Yevmenkin SDP_GET32(ssplen, req);
22007be7a6cSMaksim Yevmenkin break;
22107be7a6cSMaksim Yevmenkin }
22207be7a6cSMaksim Yevmenkin if (ssplen <= 0)
22307be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
22407be7a6cSMaksim Yevmenkin
22507be7a6cSMaksim Yevmenkin sspptr = req;
22607be7a6cSMaksim Yevmenkin req += ssplen;
22707be7a6cSMaksim Yevmenkin
22807be7a6cSMaksim Yevmenkin /* Get MaximumAttributeByteCount */
22907be7a6cSMaksim Yevmenkin if (req + 2 > req_end)
23007be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
23107be7a6cSMaksim Yevmenkin
23207be7a6cSMaksim Yevmenkin SDP_GET16(rsp_limit, req);
23307be7a6cSMaksim Yevmenkin if (rsp_limit <= 0)
23407be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
23507be7a6cSMaksim Yevmenkin
23607be7a6cSMaksim Yevmenkin /* Get size of AttributeIDList */
23707be7a6cSMaksim Yevmenkin if (req + 1 > req_end)
23807be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
23907be7a6cSMaksim Yevmenkin
24007be7a6cSMaksim Yevmenkin aidlen = 0;
24107be7a6cSMaksim Yevmenkin SDP_GET8(type, req);
24207be7a6cSMaksim Yevmenkin switch (type) {
24307be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ8:
24407be7a6cSMaksim Yevmenkin if (req + 1 > req_end)
24507be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
24607be7a6cSMaksim Yevmenkin
24707be7a6cSMaksim Yevmenkin SDP_GET8(aidlen, req);
24807be7a6cSMaksim Yevmenkin break;
24907be7a6cSMaksim Yevmenkin
25007be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ16:
25107be7a6cSMaksim Yevmenkin if (req + 2 > req_end)
25207be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
25307be7a6cSMaksim Yevmenkin
25407be7a6cSMaksim Yevmenkin SDP_GET16(aidlen, req);
25507be7a6cSMaksim Yevmenkin break;
25607be7a6cSMaksim Yevmenkin
25707be7a6cSMaksim Yevmenkin case SDP_DATA_SEQ32:
25807be7a6cSMaksim Yevmenkin if (req + 4 > req_end)
25907be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
26007be7a6cSMaksim Yevmenkin
26107be7a6cSMaksim Yevmenkin SDP_GET32(aidlen, req);
26207be7a6cSMaksim Yevmenkin break;
26307be7a6cSMaksim Yevmenkin }
26407be7a6cSMaksim Yevmenkin if (aidlen <= 0)
26507be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
26607be7a6cSMaksim Yevmenkin
26707be7a6cSMaksim Yevmenkin aidptr = req;
26807be7a6cSMaksim Yevmenkin req += aidlen;
26907be7a6cSMaksim Yevmenkin
27007be7a6cSMaksim Yevmenkin /* Get ContinuationState */
27107be7a6cSMaksim Yevmenkin if (req + 1 > req_end)
27207be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
27307be7a6cSMaksim Yevmenkin
27407be7a6cSMaksim Yevmenkin SDP_GET8(cslen, req);
27507be7a6cSMaksim Yevmenkin if (cslen != 0) {
27607be7a6cSMaksim Yevmenkin if (cslen != 2 || req_end - req != 2)
27707be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
27807be7a6cSMaksim Yevmenkin
27907be7a6cSMaksim Yevmenkin SDP_GET16(cs, req);
28007be7a6cSMaksim Yevmenkin } else
28107be7a6cSMaksim Yevmenkin cs = 0;
28207be7a6cSMaksim Yevmenkin
28307be7a6cSMaksim Yevmenkin /* Process the request. First, check continuation state */
28407be7a6cSMaksim Yevmenkin if (srv->fdidx[fd].rsp_cs != cs)
28507be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_CONTINUATION_STATE);
28607be7a6cSMaksim Yevmenkin if (srv->fdidx[fd].rsp_size > 0)
28707be7a6cSMaksim Yevmenkin return (0);
28807be7a6cSMaksim Yevmenkin
28907be7a6cSMaksim Yevmenkin /*
29007be7a6cSMaksim Yevmenkin * Service Search Attribute Response format
29107be7a6cSMaksim Yevmenkin *
29207be7a6cSMaksim Yevmenkin * value16 - 2 bytes AttributeListByteCount (not incl.)
29307be7a6cSMaksim Yevmenkin * seq8 len16 - 3 bytes
29407be7a6cSMaksim Yevmenkin * attr list - 3+ bytes AttributeLists
29507be7a6cSMaksim Yevmenkin * [ attr list ]
29607be7a6cSMaksim Yevmenkin */
29707be7a6cSMaksim Yevmenkin
29807be7a6cSMaksim Yevmenkin ptr = rsp + 3;
29907be7a6cSMaksim Yevmenkin
30007be7a6cSMaksim Yevmenkin while (ssplen > 0) {
30107be7a6cSMaksim Yevmenkin SDP_GET8(type, sspptr);
30207be7a6cSMaksim Yevmenkin ssplen --;
30307be7a6cSMaksim Yevmenkin
30407be7a6cSMaksim Yevmenkin switch (type) {
30507be7a6cSMaksim Yevmenkin case SDP_DATA_UUID16:
30607be7a6cSMaksim Yevmenkin if (ssplen < 2)
30707be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
30807be7a6cSMaksim Yevmenkin
309ee935b58SMaksim Yevmenkin memcpy(&uuid, &uuid_base, sizeof(uuid));
310ee935b58SMaksim Yevmenkin uuid.b[2] = *sspptr ++;
311ee935b58SMaksim Yevmenkin uuid.b[3] = *sspptr ++;
31207be7a6cSMaksim Yevmenkin ssplen -= 2;
31307be7a6cSMaksim Yevmenkin break;
31407be7a6cSMaksim Yevmenkin
315ee935b58SMaksim Yevmenkin case SDP_DATA_UUID32:
316ee935b58SMaksim Yevmenkin if (ssplen < 4)
317ee935b58SMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
318ee935b58SMaksim Yevmenkin
319ee935b58SMaksim Yevmenkin memcpy(&uuid, &uuid_base, sizeof(uuid));
320ee935b58SMaksim Yevmenkin uuid.b[0] = *sspptr ++;
321ee935b58SMaksim Yevmenkin uuid.b[1] = *sspptr ++;
322ee935b58SMaksim Yevmenkin uuid.b[2] = *sspptr ++;
323ee935b58SMaksim Yevmenkin uuid.b[3] = *sspptr ++;
324ee935b58SMaksim Yevmenkin ssplen -= 4;
325ee935b58SMaksim Yevmenkin break;
326ee935b58SMaksim Yevmenkin
327ee935b58SMaksim Yevmenkin case SDP_DATA_UUID128:
328ee935b58SMaksim Yevmenkin if (ssplen < 16)
329ee935b58SMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
330ee935b58SMaksim Yevmenkin
331ee935b58SMaksim Yevmenkin memcpy(uuid.b, sspptr, 16);
332ee935b58SMaksim Yevmenkin sspptr += 16;
333ee935b58SMaksim Yevmenkin ssplen -= 16;
334ee935b58SMaksim Yevmenkin break;
335ee935b58SMaksim Yevmenkin
33607be7a6cSMaksim Yevmenkin default:
33707be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
33807be7a6cSMaksim Yevmenkin /* NOT REACHED */
33907be7a6cSMaksim Yevmenkin }
34007be7a6cSMaksim Yevmenkin
34107be7a6cSMaksim Yevmenkin for (provider = provider_get_first();
34207be7a6cSMaksim Yevmenkin provider != NULL;
34307be7a6cSMaksim Yevmenkin provider = provider_get_next(provider)) {
34407be7a6cSMaksim Yevmenkin if (!provider_match_bdaddr(provider, &srv->req_sa.l2cap_bdaddr))
34507be7a6cSMaksim Yevmenkin continue;
34607be7a6cSMaksim Yevmenkin
347ee935b58SMaksim Yevmenkin memcpy(&puuid, &uuid_base, sizeof(puuid));
348ee935b58SMaksim Yevmenkin puuid.b[2] = provider->profile->uuid >> 8;
349ee935b58SMaksim Yevmenkin puuid.b[3] = provider->profile->uuid;
350ee935b58SMaksim Yevmenkin
351ee935b58SMaksim Yevmenkin if (memcmp(&uuid, &puuid, sizeof(uuid)) != 0 &&
3522d3a84f5SHans Petter Selasky memcmp(&uuid, &uuid_public_browse_group, sizeof(uuid)) != 0 &&
3532d3a84f5SHans Petter Selasky server_search_uuid(provider, &uuid) != 0)
35407be7a6cSMaksim Yevmenkin continue;
35507be7a6cSMaksim Yevmenkin
35607be7a6cSMaksim Yevmenkin cs = server_prepare_attr_list(provider,
35707be7a6cSMaksim Yevmenkin aidptr, aidptr + aidlen, ptr, rsp_end);
35807be7a6cSMaksim Yevmenkin if (cs < 0)
35907be7a6cSMaksim Yevmenkin return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES);
36007be7a6cSMaksim Yevmenkin
36107be7a6cSMaksim Yevmenkin ptr += cs;
36207be7a6cSMaksim Yevmenkin }
36307be7a6cSMaksim Yevmenkin }
36407be7a6cSMaksim Yevmenkin
36507be7a6cSMaksim Yevmenkin /* Set reply size (not counting PDU header and continuation state) */
36607be7a6cSMaksim Yevmenkin srv->fdidx[fd].rsp_limit = srv->fdidx[fd].omtu - sizeof(sdp_pdu_t) - 2;
36707be7a6cSMaksim Yevmenkin if (srv->fdidx[fd].rsp_limit > rsp_limit)
36807be7a6cSMaksim Yevmenkin srv->fdidx[fd].rsp_limit = rsp_limit;
36907be7a6cSMaksim Yevmenkin
37007be7a6cSMaksim Yevmenkin srv->fdidx[fd].rsp_size = ptr - rsp;
37107be7a6cSMaksim Yevmenkin srv->fdidx[fd].rsp_cs = 0;
37207be7a6cSMaksim Yevmenkin
37307be7a6cSMaksim Yevmenkin /* Fix AttributeLists sequence header */
37407be7a6cSMaksim Yevmenkin ptr = rsp;
37507be7a6cSMaksim Yevmenkin SDP_PUT8(SDP_DATA_SEQ16, ptr);
37607be7a6cSMaksim Yevmenkin SDP_PUT16(srv->fdidx[fd].rsp_size - 3, ptr);
37707be7a6cSMaksim Yevmenkin
37807be7a6cSMaksim Yevmenkin return (0);
37907be7a6cSMaksim Yevmenkin }
38007be7a6cSMaksim Yevmenkin
381