]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/sdpd/ssar.c
This commit was generated by cvs2svn to compensate for changes in r136136,
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / sdpd / ssar.c
1 /*
2  * ssar.c
3  *
4  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  *
28  * $Id: ssar.c,v 1.4 2004/01/12 22:54:31 max Exp $
29  * $FreeBSD$
30  */
31
32 #include <sys/queue.h>
33 #include <bluetooth.h>
34 #include <sdp.h>
35 #include <string.h>
36 #include "profile.h"
37 #include "provider.h"
38 #include "server.h"
39
40 /* from sar.c */
41 int32_t server_prepare_attr_list(provider_p const provider,
42                 uint8_t const *req, uint8_t const * const req_end,
43                 uint8_t *rsp, uint8_t const * const rsp_end);
44
45 /*
46  * Prepare SDP Service Search Attribute Response
47  */
48
49 int32_t
50 server_prepare_service_search_attribute_response(server_p srv, int32_t fd)
51 {
52         uint8_t const   *req = srv->req + sizeof(sdp_pdu_t);
53         uint8_t const   *req_end = req + ((sdp_pdu_p)(srv->req))->len;
54         uint8_t         *rsp = srv->fdidx[fd].rsp;
55         uint8_t const   *rsp_end = rsp + NG_L2CAP_MTU_MAXIMUM;
56
57         uint8_t const   *sspptr = NULL, *aidptr = NULL;
58         uint8_t         *ptr = NULL;
59
60         provider_t      *provider = NULL;
61         int32_t          type, rsp_limit, ssplen, aidlen, cslen, cs, uuid;
62
63         /*
64          * Minimal Service Search Attribute Request request
65          *
66          * seq8 len8            - 2 bytes
67          *      uuid16 value16  - 3 bytes ServiceSearchPattern
68          * value16              - 2 bytes MaximumAttributeByteCount
69          * seq8 len8            - 2 bytes
70          *      uint16 value16  - 3 bytes AttributeIDList
71          * value8               - 1 byte  ContinuationState
72          */
73
74         if (req_end - req < 13)
75                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
76
77         /* Get size of ServiceSearchPattern */
78         ssplen = 0;
79         SDP_GET8(type, req);
80         switch (type) {
81         case SDP_DATA_SEQ8:
82                 SDP_GET8(ssplen, req);
83                 break;
84
85         case SDP_DATA_SEQ16:
86                 SDP_GET16(ssplen, req);
87                 break;
88
89         case SDP_DATA_SEQ32:
90                 SDP_GET32(ssplen, req);
91                 break;
92         }
93         if (ssplen <= 0)
94                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
95
96         sspptr = req;
97         req += ssplen;
98
99         /* Get MaximumAttributeByteCount */
100         if (req + 2 > req_end)
101                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
102
103         SDP_GET16(rsp_limit, req);
104         if (rsp_limit <= 0)
105                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
106
107         /* Get size of AttributeIDList */
108         if (req + 1 > req_end)
109                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
110
111         aidlen = 0;
112         SDP_GET8(type, req);
113         switch (type) {
114         case SDP_DATA_SEQ8:
115                 if (req + 1 > req_end)
116                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
117
118                 SDP_GET8(aidlen, req);
119                 break;
120
121         case SDP_DATA_SEQ16:
122                 if (req + 2 > req_end)
123                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
124
125                 SDP_GET16(aidlen, req);
126                 break;
127
128         case SDP_DATA_SEQ32:
129                 if (req + 4 > req_end)
130                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
131
132                 SDP_GET32(aidlen, req);
133                 break;
134         }
135         if (aidlen <= 0)
136                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
137
138         aidptr = req;
139         req += aidlen;
140
141         /* Get ContinuationState */
142         if (req + 1 > req_end)
143                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
144
145         SDP_GET8(cslen, req);
146         if (cslen != 0) {
147                 if (cslen != 2 || req_end - req != 2)
148                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
149
150                 SDP_GET16(cs, req);
151         } else
152                 cs = 0;
153
154         /* Process the request. First, check continuation state */
155         if (srv->fdidx[fd].rsp_cs != cs)
156                 return (SDP_ERROR_CODE_INVALID_CONTINUATION_STATE);
157         if (srv->fdidx[fd].rsp_size > 0)
158                 return (0);
159
160         /*
161          * Service Search Attribute Response format
162          *
163          * value16              - 2 bytes  AttributeListByteCount (not incl.)
164          * seq8 len16           - 3 bytes
165          *      attr list       - 3+ bytes AttributeLists
166          *      [ attr list ]
167          */
168
169         ptr = rsp + 3;
170
171         while (ssplen > 0) {
172                 SDP_GET8(type, sspptr);
173                 ssplen --;
174
175                 switch (type) {
176                 case SDP_DATA_UUID16:
177                         if (ssplen < 2)
178                                 return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
179
180                         SDP_GET16(uuid, sspptr);
181                         ssplen -= 2;
182                         break;
183
184                 case SDP_DATA_UUID32: /* XXX FIXME */
185                 case SDP_DATA_UUID128: /* XXX FIXME */
186                 default:
187                         return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
188                         /* NOT REACHED */
189                 }
190
191                 for (provider = provider_get_first();
192                      provider != NULL;
193                      provider = provider_get_next(provider)) {
194                         if (!provider_match_bdaddr(provider, &srv->req_sa.l2cap_bdaddr))
195                                 continue;
196
197                         if (provider->profile->uuid != uuid &&
198                             SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP != uuid)
199                                 continue;
200
201                         cs = server_prepare_attr_list(provider,
202                                 aidptr, aidptr + aidlen, ptr, rsp_end);
203                         if (cs < 0)
204                                 return (SDP_ERROR_CODE_INSUFFICIENT_RESOURCES);
205
206                         ptr += cs;
207                 }
208         }
209
210         /* Set reply size (not counting PDU header and continuation state) */
211         srv->fdidx[fd].rsp_limit = srv->fdidx[fd].omtu - sizeof(sdp_pdu_t) - 2;
212         if (srv->fdidx[fd].rsp_limit > rsp_limit)
213                 srv->fdidx[fd].rsp_limit = rsp_limit;
214
215         srv->fdidx[fd].rsp_size = ptr - rsp;
216         srv->fdidx[fd].rsp_cs = 0;
217
218         /* Fix AttributeLists sequence header */
219         ptr = rsp;
220         SDP_PUT8(SDP_DATA_SEQ16, ptr);
221         SDP_PUT16(srv->fdidx[fd].rsp_size - 3, ptr);
222
223         return (0);
224 }
225