sdp_get.c revision 1.1.2.2 1 /* $NetBSD: sdp_get.c,v 1.1.2.2 2009/05/13 19:18:20 jym 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.1.2.2 2009/05/13 19:18:20 jym 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
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
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
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
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
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 if (v > UINTMAX_MAX)
192 return false;
193
194 p += 8;
195 break;
196
197 case SDP_DATA_UINT128:
198 if (p + 16 > data->end)
199 return false;
200
201 x = be64dec(p);
202 v = be64dec(p + 8);
203 if (x != 0 || v > UINTMAX_MAX)
204 return false;
205
206 p += 16;
207 break;
208
209 default:
210 return false;
211 }
212
213 data->next = p;
214 *value = (uintmax_t)v;
215 return true;
216 }
217
218 bool
219 sdp_get_int(sdp_data_t *data, intmax_t *value)
220 {
221 uint8_t *p = data->next;
222 int64_t v, x;
223
224 if (p + 1 > data->end)
225 return false;
226
227 switch (*p++) {
228 case SDP_DATA_INT8:
229 if (p + 1 > data->end)
230 return false;
231
232 v = *(int8_t *)p;
233 p += 1;
234 break;
235
236 case SDP_DATA_INT16:
237 if (p + 2 > data->end)
238 return false;
239
240 v = (int16_t)be16dec(p);
241 p += 2;
242 break;
243
244 case SDP_DATA_INT32:
245 if (p + 4 > data->end)
246 return false;
247
248 v = (int32_t)be32dec(p);
249 p += 4;
250 break;
251
252 case SDP_DATA_INT64:
253 if (p + 8 > data->end)
254 return false;
255
256 v = (int64_t)be64dec(p);
257 if (v > INTMAX_MAX || v < INTMAX_MIN)
258 return false;
259
260 p += 8;
261 break;
262
263 case SDP_DATA_INT128:
264 if (p + 16 > data->end)
265 return false;
266
267 x = (int64_t)be64dec(p);
268 v = (int64_t)be64dec(p + 8);
269 if (x == 0) {
270 if (v > INTMAX_MAX)
271 return false;
272 } else if (x == -1) {
273 if (v < INTMAX_MIN)
274 return false;
275 } else {
276 return false;
277 }
278
279 p += 16;
280 break;
281
282 default:
283 return false;
284 }
285
286 data->next = p;
287 *value = (intmax_t)v;
288 return true;
289 }
290
291 static bool
292 _sdp_get_ext(uint8_t type, sdp_data_t *data, sdp_data_t *ext)
293 {
294 uint8_t *p = data->next;
295 uint32_t l;
296
297 if (p + 1 > data->end
298 || SDP_DATA_TYPE(*p) != type)
299 return false;
300
301 switch (SDP_DATA_SIZE(*p++)) {
302 case SDP_DATA_EXT8:
303 if (p + 1 > data->end)
304 return false;
305
306 l = *p;
307 p += 1;
308 break;
309
310 case SDP_DATA_EXT16:
311 if (p + 2 > data->end)
312 return false;
313
314 l = be16dec(p);
315 p += 2;
316 break;
317
318 case SDP_DATA_EXT32:
319 if (p + 4 > data->end)
320 return false;
321
322 l = be32dec(p);
323 p += 4;
324 break;
325
326 default:
327 return false;
328 }
329
330 if (p + l > data->end)
331 return false;
332
333 data->next = p + l;
334 ext->next = p;
335 ext->end = p + l;
336 return true;
337 }
338
339 bool
340 sdp_get_seq(sdp_data_t *data, sdp_data_t *seq)
341 {
342
343 return _sdp_get_ext(SDP_DATA_SEQ, data, seq);
344 }
345
346 bool
347 sdp_get_alt(sdp_data_t *data, sdp_data_t *alt)
348 {
349
350 return _sdp_get_ext(SDP_DATA_ALT, data, alt);
351 }
352
353 bool
354 sdp_get_str(sdp_data_t *data, char **str, size_t *len)
355 {
356 sdp_data_t s;
357
358 if (!_sdp_get_ext(SDP_DATA_STR, data, &s))
359 return false;
360
361 *str = (char *)s.next;
362 *len = s.end - s.next;
363 return true;
364 }
365
366 bool
367 sdp_get_url(sdp_data_t *data, char **url, size_t *len)
368 {
369 sdp_data_t u;
370
371 if (!_sdp_get_ext(SDP_DATA_URL, data, &u))
372 return false;
373
374 *url = (char *)u.next;
375 *len = u.end - u.next;
376 return true;
377 }
378