Home | History | Annotate | Line # | Download | only in libbluetooth
      1 /*	$NetBSD: sdp_set.c,v 1.4 2011/04/05 18:58:43 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_set.c,v 1.4 2011/04/05 18:58:43 plunky Exp $");
     34 
     35 #include <bluetooth.h>
     36 #include <limits.h>
     37 #include <sdp.h>
     38 
     39 /******************************************************************************
     40  *	sdp_set_xxxx(data, value)
     41  *
     42  * update a value, will fail if data element is not of the correct type
     43  */
     44 
     45 bool
     46 sdp_set_bool(const sdp_data_t *data, bool value)
     47 {
     48 	uint8_t *p = data->next;
     49 
     50 	if (p + 2 > data->end
     51 	    || *p++ != SDP_DATA_BOOL)
     52 		return false;
     53 
     54 	*p = (value ? 0x01 : 0x00);
     55 	return true;
     56 }
     57 
     58 bool
     59 sdp_set_uint(const sdp_data_t *data, uintmax_t value)
     60 {
     61 	uint8_t *p = data->next;
     62 
     63 	if (p + 1 > data->end)
     64 		return false;
     65 
     66 	switch (*p++) {
     67 	case SDP_DATA_UINT8:
     68 		if (p + 1 > data->end
     69 		    || value > UINT8_MAX)
     70 			return false;
     71 
     72 		*p = (uint8_t)value;
     73 		break;
     74 
     75 	case SDP_DATA_UINT16:
     76 		if (p + 2 > data->end
     77 		    || value > UINT16_MAX)
     78 			return false;
     79 
     80 		be16enc(p, (uint16_t)value);
     81 		break;
     82 
     83 	case SDP_DATA_UINT32:
     84 		if (p + 4 > data->end
     85 		    || value > UINT32_MAX)
     86 			return false;
     87 
     88 		be32enc(p, (uint32_t)value);
     89 		break;
     90 
     91 	case SDP_DATA_UINT64:
     92 		if (p + 8 > data->end
     93 		    || value > UINT64_MAX)
     94 			return false;
     95 
     96 		be64enc(p, (uint64_t)value);
     97 		break;
     98 
     99 	case SDP_DATA_UINT128:
    100 		if (p + 16 > data->end)
    101 			return false;
    102 
    103 		be64enc(p + 0, (uint64_t)0);
    104 		be64enc(p + 8, (uint64_t)value);
    105 		break;
    106 
    107 	default:
    108 		return false;
    109 	}
    110 
    111 	return true;
    112 }
    113 
    114 bool
    115 sdp_set_int(const sdp_data_t *data, intmax_t value)
    116 {
    117 	uint8_t *p = data->next;
    118 
    119 	if (p + 1 > data->end)
    120 		return false;
    121 
    122 	switch (*p++) {
    123 	case SDP_DATA_INT8:
    124 		if (p + 1 > data->end
    125 		    || value > INT8_MAX
    126 		    || value < INT8_MIN)
    127 			return false;
    128 
    129 		*p = (uint8_t)value;
    130 		break;
    131 
    132 	case SDP_DATA_INT16:
    133 		if (p + 2 > data->end
    134 		    || value > INT16_MAX
    135 		    || value < INT16_MIN)
    136 			return false;
    137 
    138 		be16enc(p, (uint16_t)value);
    139 		break;
    140 
    141 	case SDP_DATA_INT32:
    142 		if (p + 4 > data->end
    143 		    || value > INT32_MAX
    144 		    || value < INT32_MIN)
    145 			return false;
    146 
    147 		be32enc(p, (uint32_t)value);
    148 		break;
    149 
    150 	case SDP_DATA_INT64:
    151 		if (p + 8 > data->end
    152 		    || value > INT64_MAX
    153 		    || value < INT64_MIN)
    154 			return false;
    155 
    156 		be64enc(p, (uint64_t)value);
    157 		break;
    158 
    159 	case SDP_DATA_INT128:
    160 		if (p + 16 > data->end)
    161 			return false;
    162 
    163 		be64enc(p + 0, (uint64_t)0);
    164 		be64enc(p + 8, (uint64_t)value);
    165 		break;
    166 
    167 	default:
    168 		return false;
    169 	}
    170 
    171 	return true;
    172 }
    173 
    174 static bool
    175 _sdp_set_ext(uint8_t type, const sdp_data_t *data, ssize_t len)
    176 {
    177 	uint8_t *p = data->next;
    178 
    179 	if (p + 1 > data->end
    180 	    || SDP_DATA_TYPE(*p) != type)
    181 		return false;
    182 
    183 	switch (SDP_DATA_SIZE(*p++)) {
    184 	case SDP_DATA_EXT8:
    185 		if (len == -1) {
    186 			if (p + 1 > data->end)
    187 				return false;
    188 
    189 			len = data->end - p - 1;
    190 		} else if (len > data->end - 1 - p)
    191 			return false;
    192 
    193 		if (len > UINT8_MAX)
    194 			return false;
    195 
    196 		*p = (uint8_t)len;
    197 		break;
    198 
    199 	case SDP_DATA_EXT16:
    200 		if (len == -1) {
    201 			if (p + 2 > data->end)
    202 				return false;
    203 
    204 			len = data->end - p - 2;
    205 		} else if (len > data->end - 2 - p)
    206 			return false;
    207 
    208 		if (len > UINT16_MAX)
    209 			return false;
    210 
    211 		be16enc(p, (uint16_t)len);
    212 		break;
    213 
    214 	case SDP_DATA_EXT32:
    215 		if (len == -1) {
    216 			if (p + 4 > data->end)
    217 				return false;
    218 
    219 			len = data->end - p - 4;
    220 		} else if (len > data->end - 4 - p)
    221 			return false;
    222 
    223 		if ((size_t)len > UINT32_MAX)
    224 			return false;
    225 
    226 		be32enc(p, (uint32_t)len);
    227 		break;
    228 
    229 	default:
    230 		return false;
    231 	}
    232 
    233 	return true;
    234 }
    235 
    236 bool
    237 sdp_set_seq(const sdp_data_t *data, ssize_t len)
    238 {
    239 
    240 	return _sdp_set_ext(SDP_DATA_SEQ, data, len);
    241 }
    242 
    243 bool
    244 sdp_set_alt(const sdp_data_t *data, ssize_t len)
    245 {
    246 
    247 	return _sdp_set_ext(SDP_DATA_ALT, data, len);
    248 }
    249