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