1 /* $NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2008 Iain Hibbert 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: sdp.c,v 1.2 2008/12/06 20:01:14 plunky Exp $"); 33 34 #include <string.h> 35 36 #define L2CAP_SOCKET_CHECKED 37 #include "sdp.h" 38 39 /* 40 * SDP data stream manipulation routines 41 */ 42 43 /* Bluetooth Base UUID */ 44 static const uuid_t BASE_UUID = { 45 0x00000000, 46 0x0000, 47 0x1000, 48 0x80, 49 0x00, 50 { 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb } 51 }; 52 53 /* 54 * _sdp_match_uuid16(ptr, limit, uuid) 55 * 56 * examine SDP data stream at ptr for a UUID, and return 57 * true if it matches the supplied short alias bluetooth UUID. 58 * limit is the first address past the end of valid data. 59 */ 60 bool 61 _sdp_match_uuid16(uint8_t **ptr, uint8_t *limit, uint16_t uuid) 62 { 63 uint8_t *p = *ptr; 64 uuid_t u1, u2; 65 66 memcpy(&u1, &BASE_UUID, sizeof(uuid_t)); 67 u1.time_low = uuid; 68 69 if (!_sdp_get_uuid(&p, limit, &u2) 70 || !uuid_equal(&u1, &u2, NULL)) 71 return false; 72 73 *ptr = p; 74 return true; 75 } 76 77 /* 78 * _sdp_get_uuid(ptr, limit, uuid) 79 * 80 * examine SDP data stream at ptr for a UUID, and extract 81 * to given storage, advancing ptr. 82 * limit is the first address past the end of valid data. 83 */ 84 bool 85 _sdp_get_uuid(uint8_t **ptr, uint8_t *limit, uuid_t *uuid) 86 { 87 uint8_t *p = *ptr; 88 89 if (p + 1 > limit) 90 return false; 91 92 switch (*p++) { 93 case SDP_DATA_UUID16: 94 if (p + 2 > limit) 95 return false; 96 97 memcpy(uuid, &BASE_UUID, sizeof(uuid_t)); 98 uuid->time_low = be16dec(p); 99 p += 2; 100 break; 101 102 case SDP_DATA_UUID32: 103 if (p + 4 > limit) 104 return false; 105 106 memcpy(uuid, &BASE_UUID, sizeof(uuid_t)); 107 uuid->time_low = be32dec(p); 108 p += 4; 109 break; 110 111 case SDP_DATA_UUID128: 112 if (p + 16 > limit) 113 return false; 114 115 uuid_dec_be(p, uuid); 116 p += 16; 117 break; 118 119 default: 120 return false; 121 } 122 123 *ptr = p; 124 return true; 125 } 126 127 /* 128 * _sdp_get_seq(ptr, limit, seq) 129 * 130 * examine SDP data stream at ptr for a sequence. return 131 * seq pointer if found and advance ptr to next object. 132 * limit is the first address past the end of valid data. 133 */ 134 bool 135 _sdp_get_seq(uint8_t **ptr, uint8_t *limit, uint8_t **seq) 136 { 137 uint8_t *p = *ptr; 138 int32_t l; 139 140 if (p + 1 > limit) 141 return false; 142 143 switch (*p++) { 144 case SDP_DATA_SEQ8: 145 if (p + 1 > limit) 146 return false; 147 148 l = *p; 149 p += 1; 150 break; 151 152 case SDP_DATA_SEQ16: 153 if (p + 2 > limit) 154 return false; 155 156 l = be16dec(p); 157 p += 2; 158 break; 159 160 case SDP_DATA_SEQ32: 161 if (p + 4 > limit) 162 return false; 163 164 l = be32dec(p); 165 p += 4; 166 break; 167 168 default: 169 return false; 170 } 171 if (p + l > limit) 172 return false; 173 174 *seq = p; 175 *ptr = p + l; 176 return true; 177 } 178 179 /* 180 * _sdp_get_uint16(ptr, limit, value) 181 * 182 * examine SDP data stream at ptr for a uint16_t, and 183 * extract to given storage, advancing ptr. 184 * limit is the first address past the end of valid data. 185 */ 186 bool 187 _sdp_get_uint16(uint8_t **ptr, uint8_t *limit, uint16_t *value) 188 { 189 uint8_t *p = *ptr; 190 uint16_t v; 191 192 if (p + 1 > limit) 193 return false; 194 195 switch (*p++) { 196 case SDP_DATA_UINT16: 197 if (p + 2 > limit) 198 return false; 199 200 v = be16dec(p); 201 p += 2; 202 break; 203 204 default: 205 return false; 206 } 207 208 *value = v; 209 *ptr = p; 210 return true; 211 } 212