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