4 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: ssar.c,v 1.4 2004/01/12 22:54:31 max Exp $
32 #include <sys/queue.h>
33 #include <bluetooth.h>
39 #include "uuid-private.h"
42 int32_t server_prepare_attr_list(provider_p
const provider
,
43 uint8_t const *req
, uint8_t const * const req_end
,
44 uint8_t *rsp
, uint8_t const * const rsp_end
);
47 * Prepare SDP Service Search Attribute Response
51 server_prepare_service_search_attribute_response(server_p srv
, int32_t fd
)
53 uint8_t const *req
= srv
->req
+ sizeof(sdp_pdu_t
);
54 uint8_t const *req_end
= req
+ ((sdp_pdu_p
)(srv
->req
))->len
;
55 uint8_t *rsp
= srv
->fdidx
[fd
].rsp
;
56 uint8_t const *rsp_end
= rsp
+ NG_L2CAP_MTU_MAXIMUM
;
58 uint8_t const *sspptr
= NULL
, *aidptr
= NULL
;
61 provider_t
*provider
= NULL
;
62 int32_t type
, rsp_limit
, ssplen
, aidlen
, cslen
, cs
;
63 uint128_t uuid
, puuid
;
66 * Minimal Service Search Attribute Request request
69 * uuid16 value16 - 3 bytes ServiceSearchPattern
70 * value16 - 2 bytes MaximumAttributeByteCount
72 * uint16 value16 - 3 bytes AttributeIDList
73 * value8 - 1 byte ContinuationState
76 if (req_end
- req
< 13)
77 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
79 /* Get size of ServiceSearchPattern */
84 SDP_GET8(ssplen
, req
);
88 SDP_GET16(ssplen
, req
);
92 SDP_GET32(ssplen
, req
);
96 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
101 /* Get MaximumAttributeByteCount */
102 if (req
+ 2 > req_end
)
103 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
105 SDP_GET16(rsp_limit
, req
);
107 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
109 /* Get size of AttributeIDList */
110 if (req
+ 1 > req_end
)
111 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
117 if (req
+ 1 > req_end
)
118 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
120 SDP_GET8(aidlen
, req
);
124 if (req
+ 2 > req_end
)
125 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
127 SDP_GET16(aidlen
, req
);
131 if (req
+ 4 > req_end
)
132 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
134 SDP_GET32(aidlen
, req
);
138 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
143 /* Get ContinuationState */
144 if (req
+ 1 > req_end
)
145 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
147 SDP_GET8(cslen
, req
);
149 if (cslen
!= 2 || req_end
- req
!= 2)
150 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
156 /* Process the request. First, check continuation state */
157 if (srv
->fdidx
[fd
].rsp_cs
!= cs
)
158 return (SDP_ERROR_CODE_INVALID_CONTINUATION_STATE
);
159 if (srv
->fdidx
[fd
].rsp_size
> 0)
163 * Service Search Attribute Response format
165 * value16 - 2 bytes AttributeListByteCount (not incl.)
166 * seq8 len16 - 3 bytes
167 * attr list - 3+ bytes AttributeLists
174 SDP_GET8(type
, sspptr
);
178 case SDP_DATA_UUID16
:
180 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
182 memcpy(&uuid
, &uuid_base
, sizeof(uuid
));
183 uuid
.b
[2] = *sspptr
++;
184 uuid
.b
[3] = *sspptr
++;
188 case SDP_DATA_UUID32
:
190 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
192 memcpy(&uuid
, &uuid_base
, sizeof(uuid
));
193 uuid
.b
[0] = *sspptr
++;
194 uuid
.b
[1] = *sspptr
++;
195 uuid
.b
[2] = *sspptr
++;
196 uuid
.b
[3] = *sspptr
++;
200 case SDP_DATA_UUID128
:
202 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
204 memcpy(uuid
.b
, sspptr
, 16);
210 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX
);
214 for (provider
= provider_get_first();
216 provider
= provider_get_next(provider
)) {
217 if (!provider_match_bdaddr(provider
, &srv
->req_sa
.l2cap_bdaddr
))
220 memcpy(&puuid
, &uuid_base
, sizeof(puuid
));
221 puuid
.b
[2] = provider
->profile
->uuid
>> 8;
222 puuid
.b
[3] = provider
->profile
->uuid
;
224 if (memcmp(&uuid
, &puuid
, sizeof(uuid
)) != 0 &&
225 memcmp(&uuid
, &uuid_public_browse_group
, sizeof(uuid
)) != 0)
228 cs
= server_prepare_attr_list(provider
,
229 aidptr
, aidptr
+ aidlen
, ptr
, rsp_end
);
231 return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES
);
237 /* Set reply size (not counting PDU header and continuation state) */
238 srv
->fdidx
[fd
].rsp_limit
= srv
->fdidx
[fd
].omtu
- sizeof(sdp_pdu_t
) - 2;
239 if (srv
->fdidx
[fd
].rsp_limit
> rsp_limit
)
240 srv
->fdidx
[fd
].rsp_limit
= rsp_limit
;
242 srv
->fdidx
[fd
].rsp_size
= ptr
- rsp
;
243 srv
->fdidx
[fd
].rsp_cs
= 0;
245 /* Fix AttributeLists sequence header */
247 SDP_PUT8(SDP_DATA_SEQ16
, ptr
);
248 SDP_PUT16(srv
->fdidx
[fd
].rsp_size
- 3, ptr
);