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