1 /* $NetBSD: sdp_get.c,v 1.3 2011/04/04 18:29:47 plunky Exp $ */
2
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Iain Hibbert.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: sdp_get.c,v 1.3 2011/04/04 18:29:47 plunky Exp $");
34
35 #include <sdp.h>
36 #include <limits.h>
37
38 /******************************************************************************
39 * sdp_get_xxxx(data, value)
40 *
41 * examine first SDP data element in list for xxx type, extracting to given
42 * storage and advancing pointer if found.
43 * - these functions will not modify data pointer unless the value was
44 * extracted successfully
45 * - these functions always update the data pointer before the value pointer,
46 * so where the value is a sdp_data_t the data struct can be discarded.
47 */
48
49 bool
sdp_get_data(sdp_data_t * data,sdp_data_t * value)50 sdp_get_data(sdp_data_t *data, sdp_data_t *value)
51 {
52 uint8_t *p = data->next;
53 ssize_t l = sdp_data_size(data);
54
55 if (l == -1
56 || p + l > data->end)
57 return false;
58
59 data->next = p + l;
60 value->next = p;
61 value->end = p + l;
62 return true;
63 }
64
65 bool
sdp_get_attr(sdp_data_t * data,uint16_t * attr,sdp_data_t * value)66 sdp_get_attr(sdp_data_t *data, uint16_t *attr, sdp_data_t *value)
67 {
68 sdp_data_t v, d = *data;
69 uintmax_t a;
70
71 if (sdp_data_type(&d) != SDP_DATA_UINT16
72 || !sdp_get_uint(&d, &a)
73 || !sdp_get_data(&d, &v))
74 return false;
75
76 *attr = (uint16_t)a;
77 *data = d;
78 *value = v;
79 return true;
80 }
81
82 bool
sdp_get_uuid(sdp_data_t * data,uuid_t * uuid)83 sdp_get_uuid(sdp_data_t *data, uuid_t *uuid)
84 {
85 uint8_t *p = data->next;
86
87 if (p + 1 > data->end)
88 return false;
89
90 switch (*p++) {
91 case SDP_DATA_UUID16:
92 if (p + 2 > data->end)
93 return false;
94
95 *uuid = BLUETOOTH_BASE_UUID;
96 uuid->time_low = be16dec(p);
97 p += 2;
98 break;
99
100 case SDP_DATA_UUID32:
101 if (p + 4 > data->end)
102 return false;
103
104 *uuid = BLUETOOTH_BASE_UUID;
105 uuid->time_low = be32dec(p);
106 p += 4;
107 break;
108
109 case SDP_DATA_UUID128:
110 if (p + 16 > data->end)
111 return false;
112
113 uuid_dec_be(p, uuid);
114 p += 16;
115 break;
116
117 default:
118 return false;
119 }
120
121 data->next = p;
122 return true;
123 }
124
125 bool
sdp_get_bool(sdp_data_t * data,bool * value)126 sdp_get_bool(sdp_data_t *data, bool *value)
127 {
128 uint8_t *p = data->next;
129 uint8_t v;
130
131 if (p + 1 > data->end)
132 return false;
133
134 switch (*p++) {
135 case SDP_DATA_BOOL:
136 if (p + 1 > data->end)
137 return false;
138
139 v = *p;
140 p += 1;
141 break;
142
143 default:
144 return false;
145 }
146
147 data->next = p;
148 *value = ((v != 0) ? true : false);
149 return true;
150 }
151
152 bool
sdp_get_uint(sdp_data_t * data,uintmax_t * value)153 sdp_get_uint(sdp_data_t *data, uintmax_t *value)
154 {
155 uint8_t *p = data->next;
156 uint64_t v, x;
157
158 if (p + 1 > data->end)
159 return false;
160
161 switch (*p++) {
162 case SDP_DATA_UINT8:
163 if (p + 1 > data->end)
164 return false;
165
166 v = *p;
167 p += 1;
168 break;
169
170 case SDP_DATA_UINT16:
171 if (p + 2 > data->end)
172 return false;
173
174 v = be16dec(p);
175 p += 2;
176 break;
177
178 case SDP_DATA_UINT32:
179 if (p + 4 > data->end)
180 return false;
181
182 v = be32dec(p);
183 p += 4;
184 break;
185
186 case SDP_DATA_UINT64:
187 if (p + 8 > data->end)
188 return false;
189
190 v = be64dec(p);
191 p += 8;
192 break;
193
194 case SDP_DATA_UINT128:
195 if (p + 16 > data->end)
196 return false;
197
198 x = be64dec(p);
199 v = be64dec(p + 8);
200 if (x != 0)
201 return false;
202
203 p += 16;
204 break;
205
206 default:
207 return false;
208 }
209
210 data->next = p;
211 *value = (uintmax_t)v;
212 return true;
213 }
214
215 bool
sdp_get_int(sdp_data_t * data,intmax_t * value)216 sdp_get_int(sdp_data_t *data, intmax_t *value)
217 {
218 uint8_t *p = data->next;
219 int64_t v, x;
220
221 if (p + 1 > data->end)
222 return false;
223
224 switch (*p++) {
225 case SDP_DATA_INT8:
226 if (p + 1 > data->end)
227 return false;
228
229 v = *(int8_t *)p;
230 p += 1;
231 break;
232
233 case SDP_DATA_INT16:
234 if (p + 2 > data->end)
235 return false;
236
237 v = (int16_t)be16dec(p);
238 p += 2;
239 break;
240
241 case SDP_DATA_INT32:
242 if (p + 4 > data->end)
243 return false;
244
245 v = (int32_t)be32dec(p);
246 p += 4;
247 break;
248
249 case SDP_DATA_INT64:
250 if (p + 8 > data->end)
251 return false;
252
253 v = (int64_t)be64dec(p);
254 p += 8;
255 break;
256
257 case SDP_DATA_INT128:
258 if (p + 16 > data->end)
259 return false;
260
261 x = (int64_t)be64dec(p);
262 v = (int64_t)be64dec(p + 8);
263 if (x == 0) {
264 if (v < 0)
265 return false;
266 } else if (x == -1) {
267 if (v >= 0)
268 return false;
269 } else {
270 return false;
271 }
272
273 p += 16;
274 break;
275
276 default:
277 return false;
278 }
279
280 data->next = p;
281 *value = (intmax_t)v;
282 return true;
283 }
284
285 static bool
_sdp_get_ext(uint8_t type,sdp_data_t * data,sdp_data_t * ext)286 _sdp_get_ext(uint8_t type, sdp_data_t *data, sdp_data_t *ext)
287 {
288 uint8_t *p = data->next;
289 uint32_t l;
290
291 if (p + 1 > data->end
292 || SDP_DATA_TYPE(*p) != type)
293 return false;
294
295 switch (SDP_DATA_SIZE(*p++)) {
296 case SDP_DATA_EXT8:
297 if (p + 1 > data->end)
298 return false;
299
300 l = *p;
301 p += 1;
302 break;
303
304 case SDP_DATA_EXT16:
305 if (p + 2 > data->end)
306 return false;
307
308 l = be16dec(p);
309 p += 2;
310 break;
311
312 case SDP_DATA_EXT32:
313 if (p + 4 > data->end)
314 return false;
315
316 l = be32dec(p);
317 p += 4;
318 break;
319
320 default:
321 return false;
322 }
323
324 if (p + l > data->end)
325 return false;
326
327 data->next = p + l;
328 ext->next = p;
329 ext->end = p + l;
330 return true;
331 }
332
333 bool
sdp_get_seq(sdp_data_t * data,sdp_data_t * seq)334 sdp_get_seq(sdp_data_t *data, sdp_data_t *seq)
335 {
336
337 return _sdp_get_ext(SDP_DATA_SEQ, data, seq);
338 }
339
340 bool
sdp_get_alt(sdp_data_t * data,sdp_data_t * alt)341 sdp_get_alt(sdp_data_t *data, sdp_data_t *alt)
342 {
343
344 return _sdp_get_ext(SDP_DATA_ALT, data, alt);
345 }
346
347 bool
sdp_get_str(sdp_data_t * data,char ** str,size_t * len)348 sdp_get_str(sdp_data_t *data, char **str, size_t *len)
349 {
350 sdp_data_t s;
351
352 if (!_sdp_get_ext(SDP_DATA_STR, data, &s))
353 return false;
354
355 *str = (char *)s.next;
356 *len = s.end - s.next;
357 return true;
358 }
359
360 bool
sdp_get_url(sdp_data_t * data,char ** url,size_t * len)361 sdp_get_url(sdp_data_t *data, char **url, size_t *len)
362 {
363 sdp_data_t u;
364
365 if (!_sdp_get_ext(SDP_DATA_URL, data, &u))
366 return false;
367
368 *url = (char *)u.next;
369 *len = u.end - u.next;
370 return true;
371 }
372