Home | History | Annotate | Line # | Download | only in libbluetooth
sdp_get.c revision 1.2
      1 /*	$NetBSD: sdp_get.c,v 1.2 2011/04/04 16:19:25 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_get.c,v 1.2 2011/04/04 16:19:25 plunky Exp $");
     34 
     35 #include <sdp.h>
     36 #include <limits.h>
     37 
     38 #if INTMAX_MAX < INT64_MAX
     39 #warning INTMAX type is not large enough to hold INT64 values
     40 #endif
     41 
     42 /******************************************************************************
     43  *	sdp_get_xxxx(data, value)
     44  *
     45  * examine first SDP data element in list for xxx type, extracting to given
     46  * storage and advancing pointer if found.
     47  * - these functions will not modify data pointer unless the value was
     48  *   extracted successfully
     49  * - these functions always update the data pointer before the value pointer,
     50  *   so where the value is a sdp_data_t the data struct can be discarded.
     51  */
     52 
     53 bool
     54 sdp_get_data(sdp_data_t *data, sdp_data_t *value)
     55 {
     56 	uint8_t *p = data->next;
     57 	ssize_t l = sdp_data_size(data);
     58 
     59 	if (l == -1
     60 	    || p + l > data->end)
     61 		return false;
     62 
     63 	data->next = p + l;
     64 	value->next = p;
     65 	value->end = p + l;
     66 	return true;
     67 }
     68 
     69 bool
     70 sdp_get_attr(sdp_data_t *data, uint16_t *attr, sdp_data_t *value)
     71 {
     72 	sdp_data_t v, d = *data;
     73 	uintmax_t a;
     74 
     75 	if (sdp_data_type(&d) != SDP_DATA_UINT16
     76 	    || !sdp_get_uint(&d, &a)
     77 	    || !sdp_get_data(&d, &v))
     78 		return false;
     79 
     80 	*attr = (uint16_t)a;
     81 	*data = d;
     82 	*value = v;
     83 	return true;
     84 }
     85 
     86 bool
     87 sdp_get_uuid(sdp_data_t *data, uuid_t *uuid)
     88 {
     89 	uint8_t *p = data->next;
     90 
     91 	if (p + 1 > data->end)
     92 		return false;
     93 
     94 	switch (*p++) {
     95 	case SDP_DATA_UUID16:
     96 		if (p + 2 > data->end)
     97 			return false;
     98 
     99 		*uuid = BLUETOOTH_BASE_UUID;
    100 		uuid->time_low = be16dec(p);
    101 		p += 2;
    102 		break;
    103 
    104 	case SDP_DATA_UUID32:
    105 		if (p + 4 > data->end)
    106 			return false;
    107 
    108 		*uuid = BLUETOOTH_BASE_UUID;
    109 		uuid->time_low = be32dec(p);
    110 		p += 4;
    111 		break;
    112 
    113 	case SDP_DATA_UUID128:
    114 		if (p + 16 > data->end)
    115 			return false;
    116 
    117 		uuid_dec_be(p, uuid);
    118 		p += 16;
    119 		break;
    120 
    121 	default:
    122 		return false;
    123 	}
    124 
    125 	data->next = p;
    126 	return true;
    127 }
    128 
    129 bool
    130 sdp_get_bool(sdp_data_t *data, bool *value)
    131 {
    132 	uint8_t *p = data->next;
    133 	uint8_t v;
    134 
    135 	if (p + 1 > data->end)
    136 		return false;
    137 
    138 	switch (*p++) {
    139 	case SDP_DATA_BOOL:
    140 		if (p + 1 > data->end)
    141 			return false;
    142 
    143 		v = *p;
    144 		p += 1;
    145 		break;
    146 
    147 	default:
    148 		return false;
    149 	}
    150 
    151 	data->next = p;
    152 	*value = ((v != 0) ? true : false);
    153 	return true;
    154 }
    155 
    156 bool
    157 sdp_get_uint(sdp_data_t *data, uintmax_t *value)
    158 {
    159 	uint8_t *p = data->next;
    160 	uint64_t v, x;
    161 
    162 	if (p + 1 > data->end)
    163 		return false;
    164 
    165 	switch (*p++) {
    166 	case SDP_DATA_UINT8:
    167 		if (p + 1 > data->end)
    168 			return false;
    169 
    170 		v = *p;
    171 		p += 1;
    172 		break;
    173 
    174 	case SDP_DATA_UINT16:
    175 		if (p + 2 > data->end)
    176 			return false;
    177 
    178 		v = be16dec(p);
    179 		p += 2;
    180 		break;
    181 
    182 	case SDP_DATA_UINT32:
    183 		if (p + 4 > data->end)
    184 			return false;
    185 
    186 		v = be32dec(p);
    187 		p += 4;
    188 		break;
    189 
    190 	case SDP_DATA_UINT64:
    191 		if (p + 8 > data->end)
    192 			return false;
    193 
    194 		v = be64dec(p);
    195 		p += 8;
    196 		break;
    197 
    198 	case SDP_DATA_UINT128:
    199 		if (p + 16 > data->end)
    200 			return false;
    201 
    202 		x = be64dec(p);
    203 		v = be64dec(p + 8);
    204 		if (x != 0)
    205 			return false;
    206 
    207 		p += 16;
    208 		break;
    209 
    210 	default:
    211 		return false;
    212 	}
    213 
    214 	data->next = p;
    215 	*value = (uintmax_t)v;
    216 	return true;
    217 }
    218 
    219 bool
    220 sdp_get_int(sdp_data_t *data, intmax_t *value)
    221 {
    222 	uint8_t *p = data->next;
    223 	int64_t v, x;
    224 
    225 	if (p + 1 > data->end)
    226 		return false;
    227 
    228 	switch (*p++) {
    229 	case SDP_DATA_INT8:
    230 		if (p + 1 > data->end)
    231 			return false;
    232 
    233 		v = *(int8_t *)p;
    234 		p += 1;
    235 		break;
    236 
    237 	case SDP_DATA_INT16:
    238 		if (p + 2 > data->end)
    239 			return false;
    240 
    241 		v = (int16_t)be16dec(p);
    242 		p += 2;
    243 		break;
    244 
    245 	case SDP_DATA_INT32:
    246 		if (p + 4 > data->end)
    247 			return false;
    248 
    249 		v = (int32_t)be32dec(p);
    250 		p += 4;
    251 		break;
    252 
    253 	case SDP_DATA_INT64:
    254 		if (p + 8 > data->end)
    255 			return false;
    256 
    257 		v = (int64_t)be64dec(p);
    258 		p += 8;
    259 		break;
    260 
    261 	case SDP_DATA_INT128:
    262 		if (p + 16 > data->end)
    263 			return false;
    264 
    265 		x = (int64_t)be64dec(p);
    266 		v = (int64_t)be64dec(p + 8);
    267 		if (x == 0) {
    268 			if (v < 0)
    269 				return false;
    270 		} else if (x == -1) {
    271 			if (v >= 0)
    272 				return false;
    273 		} else {
    274 			return false;
    275 		}
    276 
    277 		p += 16;
    278 		break;
    279 
    280 	default:
    281 		return false;
    282 	}
    283 
    284 	data->next = p;
    285 	*value = (intmax_t)v;
    286 	return true;
    287 }
    288 
    289 static bool
    290 _sdp_get_ext(uint8_t type, sdp_data_t *data, sdp_data_t *ext)
    291 {
    292 	uint8_t *p = data->next;
    293 	uint32_t l;
    294 
    295 	if (p + 1 > data->end
    296 	    || SDP_DATA_TYPE(*p) != type)
    297 		return false;
    298 
    299 	switch (SDP_DATA_SIZE(*p++)) {
    300 	case SDP_DATA_EXT8:
    301 		if (p + 1 > data->end)
    302 			return false;
    303 
    304 		l = *p;
    305 		p += 1;
    306 		break;
    307 
    308 	case SDP_DATA_EXT16:
    309 		if (p + 2 > data->end)
    310 			return false;
    311 
    312 		l = be16dec(p);
    313 		p += 2;
    314 		break;
    315 
    316 	case SDP_DATA_EXT32:
    317 		if (p + 4 > data->end)
    318 			return false;
    319 
    320 		l = be32dec(p);
    321 		p += 4;
    322 		break;
    323 
    324 	default:
    325 		return false;
    326 	}
    327 
    328 	if (p + l > data->end)
    329 		return false;
    330 
    331 	data->next = p + l;
    332 	ext->next = p;
    333 	ext->end = p + l;
    334 	return true;
    335 }
    336 
    337 bool
    338 sdp_get_seq(sdp_data_t *data, sdp_data_t *seq)
    339 {
    340 
    341 	return _sdp_get_ext(SDP_DATA_SEQ, data, seq);
    342 }
    343 
    344 bool
    345 sdp_get_alt(sdp_data_t *data, sdp_data_t *alt)
    346 {
    347 
    348 	return _sdp_get_ext(SDP_DATA_ALT, data, alt);
    349 }
    350 
    351 bool
    352 sdp_get_str(sdp_data_t *data, char **str, size_t *len)
    353 {
    354 	sdp_data_t s;
    355 
    356 	if (!_sdp_get_ext(SDP_DATA_STR, data, &s))
    357 		return false;
    358 
    359 	*str = (char *)s.next;
    360 	*len = s.end - s.next;
    361 	return true;
    362 }
    363 
    364 bool
    365 sdp_get_url(sdp_data_t *data, char **url, size_t *len)
    366 {
    367 	sdp_data_t u;
    368 
    369 	if (!_sdp_get_ext(SDP_DATA_URL, data, &u))
    370 		return false;
    371 
    372 	*url = (char *)u.next;
    373 	*len = u.end - u.next;
    374 	return true;
    375 }
    376