1 /* 2 * profile.c 3 */ 4 5 /*- 6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 7 * 8 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: profile.c,v 1.6 2004/01/13 19:31:54 max Exp $ 33 * $FreeBSD$ 34 */ 35 36 #include <sys/queue.h> 37 #define L2CAP_SOCKET_CHECKED 38 #include <bluetooth.h> 39 #include <sdp.h> 40 #include <string.h> 41 #include "profile.h" 42 #include "provider.h" 43 44 /* 45 * Lookup profile descriptor 46 */ 47 48 profile_p 49 profile_get_descriptor(uint16_t uuid) 50 { 51 extern profile_t audio_sink_profile_descriptor; 52 extern profile_t audio_source_profile_descriptor; 53 extern profile_t dun_profile_descriptor; 54 extern profile_t ftrn_profile_descriptor; 55 extern profile_t irmc_profile_descriptor; 56 extern profile_t irmc_command_profile_descriptor; 57 extern profile_t lan_profile_descriptor; 58 extern profile_t opush_profile_descriptor; 59 extern profile_t sp_profile_descriptor; 60 extern profile_t nap_profile_descriptor; 61 extern profile_t gn_profile_descriptor; 62 extern profile_t panu_profile_descriptor; 63 64 static const profile_p profiles[] = { 65 &audio_sink_profile_descriptor, 66 &audio_source_profile_descriptor, 67 &dun_profile_descriptor, 68 &ftrn_profile_descriptor, 69 &irmc_profile_descriptor, 70 &irmc_command_profile_descriptor, 71 &lan_profile_descriptor, 72 &opush_profile_descriptor, 73 &sp_profile_descriptor, 74 &nap_profile_descriptor, 75 &gn_profile_descriptor, 76 &panu_profile_descriptor 77 }; 78 79 int32_t i; 80 81 for (i = 0; i < sizeof(profiles)/sizeof(profiles[0]); i++) 82 if (profiles[i]->uuid == uuid) 83 return (profiles[i]); 84 85 return (NULL); 86 } 87 88 /* 89 * Look attribute in the profile descripror 90 */ 91 92 profile_attr_create_p 93 profile_get_attr(const profile_p profile, uint16_t attr) 94 { 95 attr_p ad = (attr_p) profile->attrs; 96 97 for (; ad->create != NULL; ad ++) 98 if (ad->attr == attr) 99 return (ad->create); 100 101 return (NULL); 102 } 103 104 /* 105 * uint32 value32 - 5 bytes 106 */ 107 108 int32_t 109 common_profile_create_service_record_handle( 110 uint8_t *buf, uint8_t const * const eob, 111 uint8_t const *data, uint32_t datalen) 112 { 113 if (buf + 5 > eob) 114 return (-1); 115 116 SDP_PUT8(SDP_DATA_UINT32, buf); 117 SDP_PUT32(((provider_p) data)->handle, buf); 118 119 return (5); 120 } 121 122 /* 123 * seq8 len8 - 2 bytes 124 * uuid16 value16 - 3 bytes 125 * [ uuid16 value ] 126 */ 127 128 int32_t 129 common_profile_create_service_class_id_list( 130 uint8_t *buf, uint8_t const * const eob, 131 uint8_t const *data, uint32_t datalen) 132 { 133 int32_t len = 3 * (datalen >>= 1); 134 135 if (len <= 0 || len > 0xff || buf + 2 + len > eob) 136 return (-1); 137 138 SDP_PUT8(SDP_DATA_SEQ8, buf); 139 SDP_PUT8(len, buf); 140 141 for (; datalen > 0; datalen --) { 142 SDP_PUT8(SDP_DATA_UUID16, buf); 143 SDP_PUT16(*((uint16_t const *)data), buf); 144 data += sizeof(uint16_t); 145 } 146 147 return (2 + len); 148 } 149 150 /* 151 * seq8 len8 - 2 bytes 152 * seq 8 len8 - 2 bytes 153 * uuid16 value16 - 3 bytes 154 * uint16 value16 - 3 bytes 155 * [ seq 8 len8 156 * uuid16 value16 157 * uint16 value16 ] 158 */ 159 160 int32_t 161 common_profile_create_bluetooth_profile_descriptor_list( 162 uint8_t *buf, uint8_t const * const eob, 163 uint8_t const *data, uint32_t datalen) 164 { 165 int32_t len = 8 * (datalen >>= 2); 166 167 if (len <= 0 || len > 0xff || buf + 2 + len > eob) 168 return (-1); 169 170 SDP_PUT8(SDP_DATA_SEQ8, buf); 171 SDP_PUT8(len, buf); 172 173 for (; datalen > 0; datalen --) { 174 SDP_PUT8(SDP_DATA_SEQ8, buf); 175 SDP_PUT8(6, buf); 176 SDP_PUT8(SDP_DATA_UUID16, buf); 177 SDP_PUT16(*((uint16_t const *)data), buf); 178 data += sizeof(uint16_t); 179 SDP_PUT8(SDP_DATA_UINT16, buf); 180 SDP_PUT16(*((uint16_t const *)data), buf); 181 data += sizeof(uint16_t); 182 } 183 184 return (2 + len); 185 } 186 187 /* 188 * seq8 len8 - 2 bytes 189 * uint16 value16 - 3 bytes 190 * uint16 value16 - 3 bytes 191 * uint16 value16 - 3 bytes 192 */ 193 194 int32_t 195 common_profile_create_language_base_attribute_id_list( 196 uint8_t *buf, uint8_t const * const eob, 197 uint8_t const *data, uint32_t datalen) 198 { 199 if (buf + 11 > eob) 200 return (-1); 201 202 SDP_PUT8(SDP_DATA_SEQ8, buf); 203 SDP_PUT8(9, buf); 204 205 /* 206 * Language code per ISO 639:1988. Use "en". 207 */ 208 209 SDP_PUT8(SDP_DATA_UINT16, buf); 210 SDP_PUT16(((0x65 << 8) | 0x6e), buf); 211 212 /* 213 * Encoding. Recommended is UTF-8. ISO639 UTF-8 MIBenum is 106 214 * (http://www.iana.org/assignments/character-sets) 215 */ 216 217 SDP_PUT8(SDP_DATA_UINT16, buf); 218 SDP_PUT16(106, buf); 219 220 /* 221 * Offset (Primary Language Base is 0x100) 222 */ 223 224 SDP_PUT8(SDP_DATA_UINT16, buf); 225 SDP_PUT16(SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID, buf); 226 227 return (11); 228 } 229 230 /* 231 * Common provider name is "FreeBSD" 232 */ 233 234 int32_t 235 common_profile_create_service_provider_name( 236 uint8_t *buf, uint8_t const * const eob, 237 uint8_t const *data, uint32_t datalen) 238 { 239 char provider_name[] = "FreeBSD"; 240 241 return (common_profile_create_string8(buf, eob, 242 (uint8_t const *) provider_name, 243 strlen(provider_name))); 244 } 245 246 /* 247 * str8 len8 string 248 */ 249 250 int32_t 251 common_profile_create_string8( 252 uint8_t *buf, uint8_t const * const eob, 253 uint8_t const *data, uint32_t datalen) 254 { 255 if (datalen == 0 || datalen > 0xff || buf + 2 + datalen > eob) 256 return (-1); 257 258 SDP_PUT8(SDP_DATA_STR8, buf); 259 SDP_PUT8(datalen, buf); 260 memcpy(buf, data, datalen); 261 262 return (2 + datalen); 263 } 264 265 /* 266 * Service Availability 267 */ 268 269 int32_t 270 common_profile_create_service_availability( 271 uint8_t *buf, uint8_t const * const eob, 272 uint8_t const *data, uint32_t datalen) 273 { 274 if (datalen != 1 || buf + 2 > eob) 275 return (-1); 276 277 SDP_PUT8(SDP_DATA_UINT8, buf); 278 SDP_PUT8(data[0], buf); 279 280 return (2); 281 } 282 283 /* 284 * seq8 len8 - 2 bytes 285 * seq8 len8 - 2 bytes 286 * uuid16 value16 - 3 bytes 287 * seq8 len8 - 2 bytes 288 * uuid16 value16 - 3 bytes 289 * uint8 value8 - 2 bytes 290 */ 291 292 int32_t 293 rfcomm_profile_create_protocol_descriptor_list( 294 uint8_t *buf, uint8_t const * const eob, 295 uint8_t const *data, uint32_t datalen) 296 { 297 if (datalen != 1 || buf + 14 > eob) 298 return (-1); 299 300 SDP_PUT8(SDP_DATA_SEQ8, buf); 301 SDP_PUT8(12, buf); 302 303 SDP_PUT8(SDP_DATA_SEQ8, buf); 304 SDP_PUT8(3, buf); 305 SDP_PUT8(SDP_DATA_UUID16, buf); 306 SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 307 308 SDP_PUT8(SDP_DATA_SEQ8, buf); 309 SDP_PUT8(5, buf); 310 SDP_PUT8(SDP_DATA_UUID16, buf); 311 SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf); 312 SDP_PUT8(SDP_DATA_UINT8, buf); 313 SDP_PUT8(*data, buf); 314 315 return (14); 316 } 317 318 /* 319 * seq8 len8 - 2 bytes 320 * seq8 len8 - 2 bytes 321 * uuid16 value16 - 3 bytes 322 * seq8 len8 - 2 bytes 323 * uuid16 value16 - 3 bytes 324 * uint8 value8 - 2 bytes 325 * seq8 len8 - 2 bytes 326 * uuid16 value16 - 3 bytes 327 */ 328 329 int32_t 330 obex_profile_create_protocol_descriptor_list( 331 uint8_t *buf, uint8_t const * const eob, 332 uint8_t const *data, uint32_t datalen) 333 { 334 if (datalen != 1 || buf + 19 > eob) 335 return (-1); 336 337 SDP_PUT8(SDP_DATA_SEQ8, buf); 338 SDP_PUT8(17, buf); 339 340 SDP_PUT8(SDP_DATA_SEQ8, buf); 341 SDP_PUT8(3, buf); 342 SDP_PUT8(SDP_DATA_UUID16, buf); 343 SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 344 345 SDP_PUT8(SDP_DATA_SEQ8, buf); 346 SDP_PUT8(5, buf); 347 SDP_PUT8(SDP_DATA_UUID16, buf); 348 SDP_PUT16(SDP_UUID_PROTOCOL_RFCOMM, buf); 349 SDP_PUT8(SDP_DATA_UINT8, buf); 350 SDP_PUT8(*data, buf); 351 352 SDP_PUT8(SDP_DATA_SEQ8, buf); 353 SDP_PUT8(3, buf); 354 SDP_PUT8(SDP_DATA_UUID16, buf); 355 SDP_PUT16(SDP_UUID_PROTOCOL_OBEX, buf); 356 357 return (19); 358 } 359 360 /* 361 * seq8 len8 362 * uint8 value8 - bytes 363 * [ uint8 value 8 ] 364 */ 365 366 int32_t 367 obex_profile_create_supported_formats_list( 368 uint8_t *buf, uint8_t const * const eob, 369 uint8_t const *data, uint32_t datalen) 370 { 371 int32_t len = 2 * datalen; 372 373 if (len <= 0 || len > 0xff || buf + 2 + len > eob) 374 return (-1); 375 376 SDP_PUT8(SDP_DATA_SEQ8, buf); 377 SDP_PUT8(len, buf); 378 379 for (; datalen > 0; datalen --) { 380 SDP_PUT8(SDP_DATA_UINT8, buf); 381 SDP_PUT8(*data++, buf); 382 } 383 384 return (2 + len); 385 } 386 387 /* 388 * do not check anything 389 */ 390 391 int32_t 392 common_profile_always_valid(uint8_t const *data, uint32_t datalen) 393 { 394 return (1); 395 } 396 397 /* 398 * verify server channel number (the first byte in the data) 399 */ 400 401 int32_t 402 common_profile_server_channel_valid(uint8_t const *data, uint32_t datalen) 403 { 404 if (data[0] < 1 || data[0] > 30) 405 return (0); 406 407 return (1); 408 } 409 410 /* 411 * verify server channel number and supported_formats_size 412 * sdp_opush_profile and sdp_irmc_profile 413 */ 414 415 int32_t 416 obex_profile_data_valid(uint8_t const *data, uint32_t datalen) 417 { 418 sdp_opush_profile_p opush = (sdp_opush_profile_p) data; 419 420 if (opush->server_channel < 1 || 421 opush->server_channel > 30 || 422 opush->supported_formats_size == 0 || 423 opush->supported_formats_size > sizeof(opush->supported_formats)) 424 return (0); 425 426 return (1); 427 } 428 429 /* 430 * BNEP protocol descriptor 431 */ 432 433 int32_t 434 bnep_profile_create_protocol_descriptor_list( 435 uint8_t *buf, uint8_t const * const eob, 436 uint8_t const *data, uint32_t datalen) 437 { 438 /* supported protocol types */ 439 uint16_t ptype[] = { 440 0x0800, /* IPv4 */ 441 0x0806, /* ARP */ 442 #ifdef INET6 443 0x86dd, /* IPv6 */ 444 #endif 445 }; 446 447 uint16_t i, psm, version = 0x0100, 448 nptypes = sizeof(ptype)/sizeof(ptype[0]), 449 nptypes_size = nptypes * 3; 450 451 if (datalen != 2 || 18 + nptypes_size > 255 || 452 buf + 20 + nptypes_size > eob) 453 return (-1); 454 455 memcpy(&psm, data, sizeof(psm)); 456 457 SDP_PUT8(SDP_DATA_SEQ8, buf); 458 SDP_PUT8(18 + nptypes_size, buf); 459 460 SDP_PUT8(SDP_DATA_SEQ8, buf); 461 SDP_PUT8(6, buf); 462 SDP_PUT8(SDP_DATA_UUID16, buf); 463 SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); 464 SDP_PUT8(SDP_DATA_UINT16, buf); 465 SDP_PUT16(psm, buf); 466 467 SDP_PUT8(SDP_DATA_SEQ8, buf); 468 SDP_PUT8(8 + nptypes_size, buf); 469 SDP_PUT8(SDP_DATA_UUID16, buf); 470 SDP_PUT16(SDP_UUID_PROTOCOL_BNEP, buf); 471 SDP_PUT8(SDP_DATA_UINT16, buf); 472 SDP_PUT16(version, buf); 473 SDP_PUT8(SDP_DATA_SEQ8, buf); 474 SDP_PUT8(nptypes_size, buf); 475 for (i = 0; i < nptypes; i ++) { 476 SDP_PUT8(SDP_DATA_UINT16, buf); 477 SDP_PUT16(ptype[i], buf); 478 } 479 480 return (20 + nptypes_size); 481 } 482 483 /* 484 * BNEP security description 485 */ 486 487 int32_t 488 bnep_profile_create_security_description( 489 uint8_t *buf, uint8_t const * const eob, 490 uint8_t const *data, uint32_t datalen) 491 { 492 uint16_t security_descr; 493 494 if (datalen != 2 || buf + 3 > eob) 495 return (-1); 496 497 memcpy(&security_descr, data, sizeof(security_descr)); 498 499 SDP_PUT8(SDP_DATA_UINT16, buf); 500 SDP_PUT16(security_descr, buf); 501 502 return (3); 503 } 504 505