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