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