sdp_put.c revision 1.5 1 /* $NetBSD: sdp_put.c,v 1.5 2011/04/05 18:19:04 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.5 2011/04/05 18:19:04 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 (len > data->end - data->next)
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 (len > data->end - 5 - p)
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 (len > data->end - 3 - p)
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 (len > data->end - 2 - p)
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, (size_t)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, (size_t)len);
373 data->next += len;
374 return true;
375 }
376