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