Home | History | Annotate | Line # | Download | only in libbluetooth
      1 /*	$NetBSD: sdp_put.c,v 1.6 2011/04/16 07:19:36 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.6 2011/04/16 07:19:36 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_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 
     76 bool
     77 sdp_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 
     92 bool
     93 sdp_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 
    105 bool
    106 sdp_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 
    118 bool
    119 sdp_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 
    131 bool
    132 sdp_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 
    144 bool
    145 sdp_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 
    163 bool
    164 sdp_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 
    176 bool
    177 sdp_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 
    189 bool
    190 sdp_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 
    202 bool
    203 sdp_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 
    215 bool
    216 sdp_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 
    234 bool
    235 sdp_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 
    247 bool
    248 sdp_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 
    260 bool
    261 sdp_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 
    273 bool
    274 sdp_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 
    286 static 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 
    334 bool
    335 sdp_put_seq(sdp_data_t *data, ssize_t len)
    336 {
    337 
    338 	return _sdp_put_ext(SDP_DATA_SEQ, data, len);
    339 }
    340 
    341 bool
    342 sdp_put_alt(sdp_data_t *data, ssize_t len)
    343 {
    344 
    345 	return _sdp_put_ext(SDP_DATA_ALT, data, len);
    346 }
    347 
    348 bool
    349 sdp_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 
    363 bool
    364 sdp_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