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