xref: /netbsd-src/lib/libbluetooth/sdp_get.c (revision 0d74ee67d327fcfc6bef9bfb0721a71bbef79746)
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