xref: /netbsd-src/lib/libbluetooth/sdp_put.c (revision 5bbcd2919f3c9469fca80698eecf112ef3185f71)
1*5bbcd291Splunky /*	$NetBSD: sdp_put.c,v 1.6 2011/04/16 07:19:36 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*5bbcd291Splunky __RCSID("$NetBSD: sdp_put.c,v 1.6 2011/04/16 07:19:36 plunky Exp $");
34dfbf818aSplunky 
35dfbf818aSplunky #include <bluetooth.h>
36dfbf818aSplunky #include <limits.h>
37dfbf818aSplunky #include <sdp.h>
38dfbf818aSplunky #include <string.h>
39dfbf818aSplunky 
40dfbf818aSplunky /******************************************************************************
41dfbf818aSplunky  *	sdp_put_xxxx(data, value)
42dfbf818aSplunky  *
43dfbf818aSplunky  * write a value to data space and advance data pointers,
44dfbf818aSplunky  * fail if data space is not large enough
45dfbf818aSplunky  */
46dfbf818aSplunky 
47dfbf818aSplunky bool
sdp_put_data(sdp_data_t * data,sdp_data_t * value)48dfbf818aSplunky sdp_put_data(sdp_data_t *data, sdp_data_t *value)
49dfbf818aSplunky {
50dfbf818aSplunky 	ssize_t len;
51dfbf818aSplunky 
52dfbf818aSplunky 	len = value->end - value->next;
53dfbf818aSplunky 
5463f86cb4Splunky 	if (len > data->end - data->next)
55dfbf818aSplunky 		return false;
56dfbf818aSplunky 
57dfbf818aSplunky 	memcpy(data->next, value->next, (size_t)len);
58dfbf818aSplunky 	data->next += len;
59dfbf818aSplunky 	return true;
60dfbf818aSplunky }
61dfbf818aSplunky 
62dfbf818aSplunky bool
sdp_put_attr(sdp_data_t * data,uint16_t attr,sdp_data_t * value)63dfbf818aSplunky sdp_put_attr(sdp_data_t *data, uint16_t attr, sdp_data_t *value)
64dfbf818aSplunky {
65dfbf818aSplunky 	sdp_data_t d = *data;
66dfbf818aSplunky 
67dfbf818aSplunky 	if (!sdp_put_uint16(&d, attr)
68*5bbcd291Splunky 	    || sdp_data_size(value) != (value->end - value->next)
69354f9cc3Splunky 	    || !sdp_put_data(&d, value))
70dfbf818aSplunky 		return false;
71dfbf818aSplunky 
72dfbf818aSplunky 	*data = d;
73dfbf818aSplunky 	return true;
74dfbf818aSplunky }
75dfbf818aSplunky 
76dfbf818aSplunky bool
sdp_put_uuid(sdp_data_t * data,const uuid_t * uuid)77dfbf818aSplunky sdp_put_uuid(sdp_data_t *data, const uuid_t *uuid)
78dfbf818aSplunky {
79dfbf818aSplunky 	uuid_t u = *uuid;
80dfbf818aSplunky 
81dfbf818aSplunky 	u.time_low = 0;
82dfbf818aSplunky 
83dfbf818aSplunky 	if (uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL) == 0)
84dfbf818aSplunky 		return sdp_put_uuid128(data, uuid);
85dfbf818aSplunky 
86dfbf818aSplunky 	if (uuid->time_low > UINT16_MAX)
87dfbf818aSplunky 		return sdp_put_uuid32(data, (uint32_t)uuid->time_low);
88dfbf818aSplunky 
89dfbf818aSplunky 	return sdp_put_uuid16(data, (uint16_t)uuid->time_low);
90dfbf818aSplunky }
91dfbf818aSplunky 
92dfbf818aSplunky bool
sdp_put_uuid16(sdp_data_t * data,uint16_t uuid)93dfbf818aSplunky sdp_put_uuid16(sdp_data_t *data, uint16_t uuid)
94dfbf818aSplunky {
95dfbf818aSplunky 
96dfbf818aSplunky 	if (data->next + 3 > data->end)
97dfbf818aSplunky 		return false;
98dfbf818aSplunky 
99dfbf818aSplunky 	data->next[0] = SDP_DATA_UUID16;
100dfbf818aSplunky 	be16enc(data->next + 1, uuid);
101dfbf818aSplunky 	data->next += 3;
102dfbf818aSplunky 	return true;
103dfbf818aSplunky }
104dfbf818aSplunky 
105dfbf818aSplunky bool
sdp_put_uuid32(sdp_data_t * data,uint32_t uuid)106dfbf818aSplunky sdp_put_uuid32(sdp_data_t *data, uint32_t uuid)
107dfbf818aSplunky {
108dfbf818aSplunky 
109dfbf818aSplunky 	if (data->next + 5 > data->end)
110dfbf818aSplunky 		return false;
111dfbf818aSplunky 
112dfbf818aSplunky 	data->next[0] = SDP_DATA_UUID32;
113dfbf818aSplunky 	be32enc(data->next + 1, uuid);
114dfbf818aSplunky 	data->next += 5;
115dfbf818aSplunky 	return true;
116dfbf818aSplunky }
117dfbf818aSplunky 
118dfbf818aSplunky bool
sdp_put_uuid128(sdp_data_t * data,const uuid_t * uuid)119dfbf818aSplunky sdp_put_uuid128(sdp_data_t *data, const uuid_t *uuid)
120dfbf818aSplunky {
121dfbf818aSplunky 
122dfbf818aSplunky 	if (data->next + 17 > data->end)
123dfbf818aSplunky 		return false;
124dfbf818aSplunky 
125dfbf818aSplunky 	data->next[0] = SDP_DATA_UUID128;
126dfbf818aSplunky 	uuid_enc_be(data->next + 1, uuid);
127dfbf818aSplunky 	data->next += 17;
128dfbf818aSplunky 	return true;
129dfbf818aSplunky }
130dfbf818aSplunky 
131dfbf818aSplunky bool
sdp_put_bool(sdp_data_t * data,bool value)132dfbf818aSplunky sdp_put_bool(sdp_data_t *data, bool value)
133dfbf818aSplunky {
134dfbf818aSplunky 
135dfbf818aSplunky 	if (data->next + 2 > data->end)
136dfbf818aSplunky 		return false;
137dfbf818aSplunky 
138dfbf818aSplunky 	data->next[0] = SDP_DATA_BOOL;
139dfbf818aSplunky 	data->next[1] = (value ? 0x01 : 0x00);
140dfbf818aSplunky 	data->next += 2;
141dfbf818aSplunky 	return true;
142dfbf818aSplunky }
143dfbf818aSplunky 
144dfbf818aSplunky bool
sdp_put_uint(sdp_data_t * data,uintmax_t value)145dfbf818aSplunky sdp_put_uint(sdp_data_t *data, uintmax_t value)
146dfbf818aSplunky {
147dfbf818aSplunky 
148dfbf818aSplunky 	if (value > UINT64_MAX)
149dfbf818aSplunky 		return false;
150dfbf818aSplunky 
151dfbf818aSplunky 	if (value > UINT32_MAX)
152dfbf818aSplunky 		return sdp_put_uint64(data, (uint64_t)value);
153dfbf818aSplunky 
154dfbf818aSplunky 	if (value > UINT16_MAX)
155dfbf818aSplunky 		return sdp_put_uint32(data, (uint32_t)value);
156dfbf818aSplunky 
157dfbf818aSplunky 	if (value > UINT8_MAX)
158dfbf818aSplunky 		return sdp_put_uint16(data, (uint16_t)value);
159dfbf818aSplunky 
160dfbf818aSplunky 	return sdp_put_uint8(data, (uint8_t)value);
161dfbf818aSplunky }
162dfbf818aSplunky 
163dfbf818aSplunky bool
sdp_put_uint8(sdp_data_t * data,uint8_t value)164dfbf818aSplunky sdp_put_uint8(sdp_data_t *data, uint8_t value)
165dfbf818aSplunky {
166dfbf818aSplunky 
167dfbf818aSplunky 	if (data->next + 2 > data->end)
168dfbf818aSplunky 		return false;
169dfbf818aSplunky 
170dfbf818aSplunky 	data->next[0] = SDP_DATA_UINT8;
171dfbf818aSplunky 	data->next[1] = value;
172dfbf818aSplunky 	data->next += 2;
173dfbf818aSplunky 	return true;
174dfbf818aSplunky }
175dfbf818aSplunky 
176dfbf818aSplunky bool
sdp_put_uint16(sdp_data_t * data,uint16_t value)177dfbf818aSplunky sdp_put_uint16(sdp_data_t *data, uint16_t value)
178dfbf818aSplunky {
179dfbf818aSplunky 
180dfbf818aSplunky 	if (data->next + 3 > data->end)
181dfbf818aSplunky 		return false;
182dfbf818aSplunky 
183dfbf818aSplunky 	data->next[0] = SDP_DATA_UINT16;
184dfbf818aSplunky 	be16enc(data->next + 1, value);
185dfbf818aSplunky 	data->next += 3;
186dfbf818aSplunky 	return true;
187dfbf818aSplunky }
188dfbf818aSplunky 
189dfbf818aSplunky bool
sdp_put_uint32(sdp_data_t * data,uint32_t value)190dfbf818aSplunky sdp_put_uint32(sdp_data_t *data, uint32_t value)
191dfbf818aSplunky {
192dfbf818aSplunky 
193dfbf818aSplunky 	if (data->next + 5 > data->end)
194dfbf818aSplunky 		return false;
195dfbf818aSplunky 
196dfbf818aSplunky 	data->next[0] = SDP_DATA_UINT32;
197dfbf818aSplunky 	be32enc(data->next + 1, value);
198dfbf818aSplunky 	data->next += 5;
199dfbf818aSplunky 	return true;
200dfbf818aSplunky }
201dfbf818aSplunky 
202dfbf818aSplunky bool
sdp_put_uint64(sdp_data_t * data,uint64_t value)203dfbf818aSplunky sdp_put_uint64(sdp_data_t *data, uint64_t value)
204dfbf818aSplunky {
205dfbf818aSplunky 
206dfbf818aSplunky 	if (data->next + 9 > data->end)
207dfbf818aSplunky 		return false;
208dfbf818aSplunky 
209dfbf818aSplunky 	data->next[0] = SDP_DATA_UINT64;
210dfbf818aSplunky 	be64enc(data->next + 1, value);
211dfbf818aSplunky 	data->next += 9;
212dfbf818aSplunky 	return true;
213dfbf818aSplunky }
214dfbf818aSplunky 
215dfbf818aSplunky bool
sdp_put_int(sdp_data_t * data,intmax_t value)216dfbf818aSplunky sdp_put_int(sdp_data_t *data, intmax_t value)
217dfbf818aSplunky {
218dfbf818aSplunky 
219dfbf818aSplunky 	if (value > INT64_MAX || value < INT64_MIN)
220dfbf818aSplunky 		return false;
221dfbf818aSplunky 
222dfbf818aSplunky 	if (value > INT32_MAX || value < INT32_MIN)
223dfbf818aSplunky 		return sdp_put_int64(data, (int64_t)value);
224dfbf818aSplunky 
225dfbf818aSplunky 	if (value > INT16_MAX || value < INT16_MIN)
226dfbf818aSplunky 		return sdp_put_int32(data, (int32_t)value);
227dfbf818aSplunky 
228dfbf818aSplunky 	if (value > INT8_MAX || value < INT8_MIN)
229dfbf818aSplunky 		return sdp_put_int16(data, (int16_t)value);
230dfbf818aSplunky 
231dfbf818aSplunky 	return sdp_put_int8(data, (int8_t)value);
232dfbf818aSplunky }
233dfbf818aSplunky 
234dfbf818aSplunky bool
sdp_put_int8(sdp_data_t * data,int8_t value)235dfbf818aSplunky sdp_put_int8(sdp_data_t *data, int8_t value)
236dfbf818aSplunky {
237dfbf818aSplunky 
238dfbf818aSplunky 	if (data->next + 2 > data->end)
239dfbf818aSplunky 		return false;
240dfbf818aSplunky 
241dfbf818aSplunky 	data->next[0] = SDP_DATA_INT8;
242dfbf818aSplunky 	data->next[1] = (uint8_t)value;
243dfbf818aSplunky 	data->next += 2;
244dfbf818aSplunky 	return true;
245dfbf818aSplunky }
246dfbf818aSplunky 
247dfbf818aSplunky bool
sdp_put_int16(sdp_data_t * data,int16_t value)248dfbf818aSplunky sdp_put_int16(sdp_data_t *data, int16_t value)
249dfbf818aSplunky {
250dfbf818aSplunky 
251dfbf818aSplunky 	if (data->next + 3 > data->end)
252dfbf818aSplunky 		return false;
253dfbf818aSplunky 
254dfbf818aSplunky 	data->next[0] = SDP_DATA_INT16;
255dfbf818aSplunky 	be16enc(data->next + 1, (uint16_t)value);
256dfbf818aSplunky 	data->next += 3;
257dfbf818aSplunky 	return true;
258dfbf818aSplunky }
259dfbf818aSplunky 
260dfbf818aSplunky bool
sdp_put_int32(sdp_data_t * data,int32_t value)261dfbf818aSplunky sdp_put_int32(sdp_data_t *data, int32_t value)
262dfbf818aSplunky {
263dfbf818aSplunky 
264dfbf818aSplunky 	if (data->next + 5 > data->end)
265dfbf818aSplunky 		return false;
266dfbf818aSplunky 
267dfbf818aSplunky 	data->next[0] = SDP_DATA_INT32;
268dfbf818aSplunky 	be32enc(data->next + 1, (uint32_t)value);
269dfbf818aSplunky 	data->next += 5;
270dfbf818aSplunky 	return true;
271dfbf818aSplunky }
272dfbf818aSplunky 
273dfbf818aSplunky bool
sdp_put_int64(sdp_data_t * data,int64_t value)274dfbf818aSplunky sdp_put_int64(sdp_data_t *data, int64_t value)
275dfbf818aSplunky {
276dfbf818aSplunky 
277dfbf818aSplunky 	if (data->next + 9 > data->end)
278dfbf818aSplunky 		return false;
279dfbf818aSplunky 
280dfbf818aSplunky 	data->next[0] = SDP_DATA_INT64;
281dfbf818aSplunky 	be64enc(data->next + 1, (uint64_t)value);
282dfbf818aSplunky 	data->next += 9;
283dfbf818aSplunky 	return true;
284dfbf818aSplunky }
285dfbf818aSplunky 
286dfbf818aSplunky static bool
_sdp_put_ext(uint8_t type,sdp_data_t * data,ssize_t len)287dfbf818aSplunky _sdp_put_ext(uint8_t type, sdp_data_t *data, ssize_t len)
288dfbf818aSplunky {
289dfbf818aSplunky 	uint8_t *p = data->next;
290dfbf818aSplunky 
291dfbf818aSplunky 	if (len == -1) {
292dfbf818aSplunky 		if (p + 2 > data->end)
293dfbf818aSplunky 			return false;
294dfbf818aSplunky 
295dfbf818aSplunky 		len = data->end - p - 2;
296dfbf818aSplunky 
297dfbf818aSplunky 		if (len > UINT8_MAX)
298dfbf818aSplunky 			len -= 1;
299dfbf818aSplunky 
300dfbf818aSplunky 		if (len > UINT16_MAX)
301dfbf818aSplunky 			len -= 2;
302dfbf818aSplunky 	}
303dfbf818aSplunky 
3048ebedbbbSplunky 	if ((size_t)len > UINT32_MAX)
305dfbf818aSplunky 		return false;
306dfbf818aSplunky 
3078ebedbbbSplunky 	if ((size_t)len > UINT16_MAX) {
30863f86cb4Splunky 		if (len > data->end - 5 - p)
309dfbf818aSplunky 			return false;
310dfbf818aSplunky 
311dfbf818aSplunky 		p[0] = type | SDP_DATA_EXT32;
312dfbf818aSplunky 		be32enc(p + 1, (uint32_t)len);
313dfbf818aSplunky 		p += 5;
3148ebedbbbSplunky 	} else if ((size_t)len > UINT8_MAX) {
31563f86cb4Splunky 		if (len > data->end - 3 - p)
316dfbf818aSplunky 			return false;
317dfbf818aSplunky 
318dfbf818aSplunky 		p[0] = type | SDP_DATA_EXT16;
319dfbf818aSplunky 		be16enc(p + 1, (uint16_t)len);
320dfbf818aSplunky 		p += 3;
321dfbf818aSplunky 	} else {
32263f86cb4Splunky 		if (len > data->end - 2 - p)
323dfbf818aSplunky 			return false;
324dfbf818aSplunky 
325dfbf818aSplunky 		p[0] = type | SDP_DATA_EXT8;
326dfbf818aSplunky 		p[1] = (uint8_t)len;
327dfbf818aSplunky 		p += 2;
328dfbf818aSplunky 	}
329dfbf818aSplunky 
330dfbf818aSplunky 	data->next = p;
331dfbf818aSplunky 	return true;
332dfbf818aSplunky }
333dfbf818aSplunky 
334dfbf818aSplunky bool
sdp_put_seq(sdp_data_t * data,ssize_t len)335dfbf818aSplunky sdp_put_seq(sdp_data_t *data, ssize_t len)
336dfbf818aSplunky {
337dfbf818aSplunky 
338dfbf818aSplunky 	return _sdp_put_ext(SDP_DATA_SEQ, data, len);
339dfbf818aSplunky }
340dfbf818aSplunky 
341dfbf818aSplunky bool
sdp_put_alt(sdp_data_t * data,ssize_t len)342dfbf818aSplunky sdp_put_alt(sdp_data_t *data, ssize_t len)
343dfbf818aSplunky {
344dfbf818aSplunky 
345dfbf818aSplunky 	return _sdp_put_ext(SDP_DATA_ALT, data, len);
346dfbf818aSplunky }
347dfbf818aSplunky 
348dfbf818aSplunky bool
sdp_put_str(sdp_data_t * data,const char * str,ssize_t len)349dfbf818aSplunky sdp_put_str(sdp_data_t *data, const char *str, ssize_t len)
350dfbf818aSplunky {
351dfbf818aSplunky 
352dfbf818aSplunky 	if (len == -1)
353dfbf818aSplunky 		len = strlen(str);
354dfbf818aSplunky 
355dfbf818aSplunky 	if (!_sdp_put_ext(SDP_DATA_STR, data, len))
356dfbf818aSplunky 		return false;
357dfbf818aSplunky 
3589dc6fb5cSplunky 	memcpy(data->next, str, (size_t)len);
359dfbf818aSplunky 	data->next += len;
360dfbf818aSplunky 	return true;
361dfbf818aSplunky }
362dfbf818aSplunky 
363dfbf818aSplunky bool
sdp_put_url(sdp_data_t * data,const char * url,ssize_t len)364dfbf818aSplunky sdp_put_url(sdp_data_t *data, const char *url, ssize_t len)
365dfbf818aSplunky {
366dfbf818aSplunky 
367dfbf818aSplunky 	if (len == -1)
368dfbf818aSplunky 		len = strlen(url);
369dfbf818aSplunky 
370dfbf818aSplunky 	if (!_sdp_put_ext(SDP_DATA_URL, data, len))
371dfbf818aSplunky 		return false;
372dfbf818aSplunky 
3739dc6fb5cSplunky 	memcpy(data->next, url, (size_t)len);
374dfbf818aSplunky 	data->next += len;
375dfbf818aSplunky 	return true;
376dfbf818aSplunky }
377