Sync usage with man page.
[netbsd-mini2440.git] / lib / libbluetooth / sdp_get.c
blob0b163aaf2fcba56a16e258a0ebf8ce75f812b068
1 /* $NetBSD: sdp_get.c$ */
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Iain Hibbert.
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.
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.
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: sdp_get.c$");
35 #include <sdp.h>
36 #include <limits.h>
38 /******************************************************************************
39 * sdp_get_xxxx(data, value)
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.
49 bool
50 sdp_get_data(sdp_data_t *data, sdp_data_t *value)
52 uint8_t *p = data->next;
53 ssize_t l = sdp_data_size(data);
55 if (l == -1
56 || p + l > data->end)
57 return false;
59 data->next = p + l;
60 value->next = p;
61 value->end = p + l;
62 return true;
65 bool
66 sdp_get_attr(sdp_data_t *data, uint16_t *attr, sdp_data_t *value)
68 sdp_data_t v, d = *data;
69 uintmax_t a;
71 if (sdp_data_type(&d) != SDP_DATA_UINT16
72 || !sdp_get_uint(&d, &a)
73 || !sdp_get_data(&d, &v))
74 return false;
76 *attr = (uint16_t)a;
77 *data = d;
78 *value = v;
79 return true;
82 bool
83 sdp_get_uuid(sdp_data_t *data, uuid_t *uuid)
85 uint8_t *p = data->next;
87 if (p + 1 > data->end)
88 return false;
90 switch (*p++) {
91 case SDP_DATA_UUID16:
92 if (p + 2 > data->end)
93 return false;
95 *uuid = BLUETOOTH_BASE_UUID;
96 uuid->time_low = be16dec(p);
97 p += 2;
98 break;
100 case SDP_DATA_UUID32:
101 if (p + 4 > data->end)
102 return false;
104 *uuid = BLUETOOTH_BASE_UUID;
105 uuid->time_low = be32dec(p);
106 p += 4;
107 break;
109 case SDP_DATA_UUID128:
110 if (p + 16 > data->end)
111 return false;
113 uuid_dec_be(p, uuid);
114 p += 16;
115 break;
117 default:
118 return false;
121 data->next = p;
122 return true;
125 bool
126 sdp_get_bool(sdp_data_t *data, bool *value)
128 uint8_t *p = data->next;
129 uint8_t v;
131 if (p + 1 > data->end)
132 return false;
134 switch (*p++) {
135 case SDP_DATA_BOOL:
136 if (p + 1 > data->end)
137 return false;
139 v = *p;
140 p += 1;
141 break;
143 default:
144 return false;
147 data->next = p;
148 *value = ((v != 0) ? true : false);
149 return true;
152 bool
153 sdp_get_uint(sdp_data_t *data, uintmax_t *value)
155 uint8_t *p = data->next;
156 uint64_t v, x;
158 if (p + 1 > data->end)
159 return false;
161 switch (*p++) {
162 case SDP_DATA_UINT8:
163 if (p + 1 > data->end)
164 return false;
166 v = *p;
167 p += 1;
168 break;
170 case SDP_DATA_UINT16:
171 if (p + 2 > data->end)
172 return false;
174 v = be16dec(p);
175 p += 2;
176 break;
178 case SDP_DATA_UINT32:
179 if (p + 4 > data->end)
180 return false;
182 v = be32dec(p);
183 p += 4;
184 break;
186 case SDP_DATA_UINT64:
187 if (p + 8 > data->end)
188 return false;
190 v = be64dec(p);
191 if (v > UINTMAX_MAX)
192 return false;
194 p += 8;
195 break;
197 case SDP_DATA_UINT128:
198 if (p + 16 > data->end)
199 return false;
201 x = be64dec(p);
202 v = be64dec(p + 8);
203 if (x != 0 || v > UINTMAX_MAX)
204 return false;
206 p += 16;
207 break;
209 default:
210 return false;
213 data->next = p;
214 *value = (uintmax_t)v;
215 return true;
218 bool
219 sdp_get_int(sdp_data_t *data, intmax_t *value)
221 uint8_t *p = data->next;
222 int64_t v, x;
224 if (p + 1 > data->end)
225 return false;
227 switch (*p++) {
228 case SDP_DATA_INT8:
229 if (p + 1 > data->end)
230 return false;
232 v = *(int8_t *)p;
233 p += 1;
234 break;
236 case SDP_DATA_INT16:
237 if (p + 2 > data->end)
238 return false;
240 v = (int16_t)be16dec(p);
241 p += 2;
242 break;
244 case SDP_DATA_INT32:
245 if (p + 4 > data->end)
246 return false;
248 v = (int32_t)be32dec(p);
249 p += 4;
250 break;
252 case SDP_DATA_INT64:
253 if (p + 8 > data->end)
254 return false;
256 v = (int64_t)be64dec(p);
257 if (v > INTMAX_MAX || v < INTMAX_MIN)
258 return false;
260 p += 8;
261 break;
263 case SDP_DATA_INT128:
264 if (p + 16 > data->end)
265 return false;
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;
279 p += 16;
280 break;
282 default:
283 return false;
286 data->next = p;
287 *value = (intmax_t)v;
288 return true;
291 static bool
292 _sdp_get_ext(uint8_t type, sdp_data_t *data, sdp_data_t *ext)
294 uint8_t *p = data->next;
295 uint32_t l;
297 if (p + 1 > data->end
298 || SDP_DATA_TYPE(*p) != type)
299 return false;
301 switch (SDP_DATA_SIZE(*p++)) {
302 case SDP_DATA_EXT8:
303 if (p + 1 > data->end)
304 return false;
306 l = *p;
307 p += 1;
308 break;
310 case SDP_DATA_EXT16:
311 if (p + 2 > data->end)
312 return false;
314 l = be16dec(p);
315 p += 2;
316 break;
318 case SDP_DATA_EXT32:
319 if (p + 4 > data->end)
320 return false;
322 l = be32dec(p);
323 p += 4;
324 break;
326 default:
327 return false;
330 if (p + l > data->end)
331 return false;
333 data->next = p + l;
334 ext->next = p;
335 ext->end = p + l;
336 return true;
339 bool
340 sdp_get_seq(sdp_data_t *data, sdp_data_t *seq)
343 return _sdp_get_ext(SDP_DATA_SEQ, data, seq);
346 bool
347 sdp_get_alt(sdp_data_t *data, sdp_data_t *alt)
350 return _sdp_get_ext(SDP_DATA_ALT, data, alt);
353 bool
354 sdp_get_str(sdp_data_t *data, char **str, size_t *len)
356 sdp_data_t s;
358 if (!_sdp_get_ext(SDP_DATA_STR, data, &s))
359 return false;
361 *str = (char *)s.next;
362 *len = s.end - s.next;
363 return true;
366 bool
367 sdp_get_url(sdp_data_t *data, char **url, size_t *len)
369 sdp_data_t u;
371 if (!_sdp_get_ext(SDP_DATA_URL, data, &u))
372 return false;
374 *url = (char *)u.next;
375 *len = u.end - u.next;
376 return true;