]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/sdpd/ssar.c
Upgrade to OpenSSH 7.6p1. This will be followed shortly by 7.7p1.
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / sdpd / ssar.c
1 /*-
2  * ssar.c
3  *
4  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5  *
6  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: ssar.c,v 1.4 2004/01/12 22:54:31 max Exp $
31  * $FreeBSD$
32  */
33
34 #include <sys/queue.h>
35 #define L2CAP_SOCKET_CHECKED
36 #include <bluetooth.h>
37 #include <sdp.h>
38 #include <string.h>
39 #include "profile.h"
40 #include "provider.h"
41 #include "server.h"
42 #include "uuid-private.h"
43
44 /* from sar.c */
45 int32_t server_prepare_attr_list(provider_p const provider,
46                 uint8_t const *req, uint8_t const * const req_end,
47                 uint8_t *rsp, uint8_t const * const rsp_end);
48
49 /*
50  * Prepare SDP Service Search Attribute Response
51  */
52
53 int32_t
54 server_prepare_service_search_attribute_response(server_p srv, int32_t fd)
55 {
56         uint8_t const   *req = srv->req + sizeof(sdp_pdu_t);
57         uint8_t const   *req_end = req + ((sdp_pdu_p)(srv->req))->len;
58         uint8_t         *rsp = srv->fdidx[fd].rsp;
59         uint8_t const   *rsp_end = rsp + NG_L2CAP_MTU_MAXIMUM;
60
61         uint8_t const   *sspptr = NULL, *aidptr = NULL;
62         uint8_t         *ptr = NULL;
63
64         provider_t      *provider = NULL;
65         int32_t          type, rsp_limit, ssplen, aidlen, cslen, cs;
66         uint128_t        uuid, puuid;
67
68         /*
69          * Minimal Service Search Attribute Request request
70          *
71          * seq8 len8            - 2 bytes
72          *      uuid16 value16  - 3 bytes ServiceSearchPattern
73          * value16              - 2 bytes MaximumAttributeByteCount
74          * seq8 len8            - 2 bytes
75          *      uint16 value16  - 3 bytes AttributeIDList
76          * value8               - 1 byte  ContinuationState
77          */
78
79         if (req_end - req < 13)
80                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
81
82         /* Get size of ServiceSearchPattern */
83         ssplen = 0;
84         SDP_GET8(type, req);
85         switch (type) {
86         case SDP_DATA_SEQ8:
87                 SDP_GET8(ssplen, req);
88                 break;
89
90         case SDP_DATA_SEQ16:
91                 SDP_GET16(ssplen, req);
92                 break;
93
94         case SDP_DATA_SEQ32:
95                 SDP_GET32(ssplen, req);
96                 break;
97         }
98         if (ssplen <= 0)
99                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
100
101         sspptr = req;
102         req += ssplen;
103
104         /* Get MaximumAttributeByteCount */
105         if (req + 2 > req_end)
106                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
107
108         SDP_GET16(rsp_limit, req);
109         if (rsp_limit <= 0)
110                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
111
112         /* Get size of AttributeIDList */
113         if (req + 1 > req_end)
114                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
115
116         aidlen = 0;
117         SDP_GET8(type, req);
118         switch (type) {
119         case SDP_DATA_SEQ8:
120                 if (req + 1 > req_end)
121                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
122
123                 SDP_GET8(aidlen, req);
124                 break;
125
126         case SDP_DATA_SEQ16:
127                 if (req + 2 > req_end)
128                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
129
130                 SDP_GET16(aidlen, req);
131                 break;
132
133         case SDP_DATA_SEQ32:
134                 if (req + 4 > req_end)
135                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
136
137                 SDP_GET32(aidlen, req);
138                 break;
139         }
140         if (aidlen <= 0)
141                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
142
143         aidptr = req;
144         req += aidlen;
145
146         /* Get ContinuationState */
147         if (req + 1 > req_end)
148                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
149
150         SDP_GET8(cslen, req);
151         if (cslen != 0) {
152                 if (cslen != 2 || req_end - req != 2)
153                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
154
155                 SDP_GET16(cs, req);
156         } else
157                 cs = 0;
158
159         /* Process the request. First, check continuation state */
160         if (srv->fdidx[fd].rsp_cs != cs)
161                 return (SDP_ERROR_CODE_INVALID_CONTINUATION_STATE);
162         if (srv->fdidx[fd].rsp_size > 0)
163                 return (0);
164
165         /*
166          * Service Search Attribute Response format
167          *
168          * value16              - 2 bytes  AttributeListByteCount (not incl.)
169          * seq8 len16           - 3 bytes
170          *      attr list       - 3+ bytes AttributeLists
171          *      [ attr list ]
172          */
173
174         ptr = rsp + 3;
175
176         while (ssplen > 0) {
177                 SDP_GET8(type, sspptr);
178                 ssplen --;
179
180                 switch (type) {
181                 case SDP_DATA_UUID16:
182                         if (ssplen < 2)
183                                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
184
185                         memcpy(&uuid, &uuid_base, sizeof(uuid));
186                         uuid.b[2] = *sspptr ++;
187                         uuid.b[3] = *sspptr ++;
188                         ssplen -= 2;
189                         break;
190
191                 case SDP_DATA_UUID32:
192                         if (ssplen < 4)
193                                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
194
195                         memcpy(&uuid, &uuid_base, sizeof(uuid));
196                         uuid.b[0] = *sspptr ++;
197                         uuid.b[1] = *sspptr ++;
198                         uuid.b[2] = *sspptr ++;
199                         uuid.b[3] = *sspptr ++;
200                         ssplen -= 4;
201                         break;
202
203                 case SDP_DATA_UUID128:
204                         if (ssplen < 16)
205                                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
206
207                         memcpy(uuid.b, sspptr, 16);
208                         sspptr += 16;   
209                         ssplen -= 16; 
210                         break;
211
212                 default:
213                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
214                         /* NOT REACHED */
215                 }
216
217                 for (provider = provider_get_first();
218                      provider != NULL;
219                      provider = provider_get_next(provider)) {
220                         if (!provider_match_bdaddr(provider, &srv->req_sa.l2cap_bdaddr))
221                                 continue;
222
223                         memcpy(&puuid, &uuid_base, sizeof(puuid));
224                         puuid.b[2] = provider->profile->uuid >> 8;
225                         puuid.b[3] = provider->profile->uuid;
226
227                         if (memcmp(&uuid, &puuid, sizeof(uuid)) != 0 &&
228                             memcmp(&uuid, &uuid_public_browse_group, sizeof(uuid)) != 0)
229                                 continue;
230
231                         cs = server_prepare_attr_list(provider,
232                                 aidptr, aidptr + aidlen, ptr, rsp_end);
233                         if (cs < 0)
234                                 return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES);
235
236                         ptr += cs;
237                 }
238         }
239
240         /* Set reply size (not counting PDU header and continuation state) */
241         srv->fdidx[fd].rsp_limit = srv->fdidx[fd].omtu - sizeof(sdp_pdu_t) - 2;
242         if (srv->fdidx[fd].rsp_limit > rsp_limit)
243                 srv->fdidx[fd].rsp_limit = rsp_limit;
244
245         srv->fdidx[fd].rsp_size = ptr - rsp;
246         srv->fdidx[fd].rsp_cs = 0;
247
248         /* Fix AttributeLists sequence header */
249         ptr = rsp;
250         SDP_PUT8(SDP_DATA_SEQ16, ptr);
251         SDP_PUT16(srv->fdidx[fd].rsp_size - 3, ptr);
252
253         return (0);
254 }
255