sdp.c revision a8efcfa5ca81ef29e4d56dac70761d9b9ffc9708
1/* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2001-2002 Nokia Corporation 6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> 7 * Copyright (C) 2002-2004 Marcel Holtmann <marcel@holtmann.org> 8 * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com> 9 * 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation; 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 18 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 19 * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 * 24 * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 25 * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 26 * SOFTWARE IS DISCLAIMED. 27 * 28 * 29 * $Id$ 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include <config.h> 34#endif 35 36#include <stdio.h> 37#include <errno.h> 38#include <unistd.h> 39#include <stdlib.h> 40#include <malloc.h> 41#include <sys/un.h> 42#include <sys/socket.h> 43 44#include <bluetooth/bluetooth.h> 45#include <bluetooth/hci.h> 46#include <bluetooth/hci_lib.h> 47#include <bluetooth/l2cap.h> 48#include <bluetooth/sdp.h> 49#include <bluetooth/sdp_lib.h> 50#include <bluetooth/sdp_internal.h> 51 52#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" 53 54static uint128_t *bluetooth_base_uuid = NULL; 55 56/* Message structure. */ 57struct tupla { 58 int index; 59 char *str; 60}; 61 62static struct tupla Protocol[] = { 63 { SDP_UUID, "SDP" }, 64 { RFCOMM_UUID, "RFCOMM" }, 65 { TCS_BIN_UUID, "TCS-BIN" }, 66 { L2CAP_UUID, "L2CAP" }, 67 { IP_UUID, "IP" }, 68 { UDP_UUID, "UDP" }, 69 { TCP_UUID, "TCP" }, 70 { TCS_AT_UUID, "TCS-AT" }, 71 { OBEX_UUID, "OBEX" }, 72 { FTP_UUID, "FTP" }, 73 { HTTP_UUID, "HTTP" }, 74 { WSP_UUID, "WSP" }, 75 { BNEP_UUID, "BNEP" }, 76 { HIDP_UUID, "HIDP" }, 77 { CMTP_UUID, "CMTP" }, 78 { 0 } 79}; 80 81static struct tupla ServiceClass[] = { 82 { SDP_SERVER_SVCLASS_ID, "SDP Server" }, 83 { BROWSE_GRP_DESC_SVCLASS_ID, "Browse Group Descriptor" }, 84 { PUBLIC_BROWSE_GROUP, "Public Browse Group" }, 85 { SERIAL_PORT_SVCLASS_ID, "Serial Port" }, 86 { LAN_ACCESS_SVCLASS_ID, "LAN Access Using PPP" }, 87 { DIALUP_NET_SVCLASS_ID, "Dialup Networking" }, 88 { IRMC_SYNC_SVCLASS_ID, "IrMCSync" }, 89 { OBEX_OBJPUSH_SVCLASS_ID, "OBEX Object Push" }, 90 { OBEX_FILETRANS_SVCLASS_ID, "OBEX File Transfer" }, 91 { IRMC_SYNC_CMD_SVCLASS_ID, "IrMCSync Command" }, 92 { HEADSET_SVCLASS_ID, "Headset" }, 93 { CORDLESS_TELEPHONY_SVCLASS_ID,"Cordless Telephony" }, 94 { INTERCOM_SVCLASS_ID, "Intercom" }, 95 { FAX_SVCLASS_ID, "Fax" }, 96 { HEADSET_AGW_SVCLASS_ID, "Headset Audio Gateway" }, 97 { PNP_INFO_SVCLASS_ID, "PnP Information" }, 98 { GENERIC_NETWORKING_SVCLASS_ID,"Generic Networking" }, 99 { GENERIC_FILETRANS_SVCLASS_ID, "Generic File Transfer" }, 100 { GENERIC_AUDIO_SVCLASS_ID, "Generic Audio" }, 101 { GENERIC_TELEPHONY_SVCLASS_ID, "Generic Telephony" }, 102 { PANU_SVCLASS_ID, "PAN user" }, 103 { NAP_SVCLASS_ID, "Network access point" }, 104 { GN_SVCLASS_ID, "PAN group network" }, 105 { HID_SVCLASS_ID, "Human Interface Device" }, 106 { CIP_SVCLASS_ID, "Common ISDN Access" }, 107 { 0 } 108}; 109 110static struct tupla Profile[] = { 111 { SERIAL_PORT_PROFILE_ID, "Serial Port" }, 112 { LAN_ACCESS_PROFILE_ID, "LAN Access Using PPP" }, 113 { DIALUP_NET_PROFILE_ID, "Dialup Networking" }, 114 { IRMC_SYNC_PROFILE_ID, "IrMCSync" }, 115 { OBEX_OBJPUSH_PROFILE_ID, "OBEX Object Push" }, 116 { OBEX_FILETRANS_PROFILE_ID, "OBEX File Transfer" }, 117 { IRMC_SYNC_CMD_PROFILE_ID, "IrMCSync Command" }, 118 { HEADSET_PROFILE_ID, "Headset" }, 119 { CORDLESS_TELEPHONY_PROFILE_ID, "Cordless Telephony" }, 120 { INTERCOM_PROFILE_ID, "Intercom" }, 121 { FAX_PROFILE_ID, "Fax" }, 122 { HEADSET_AGW_PROFILE_ID, "Headset Audio Gateway" }, 123 { PANU_PROFILE_ID, "PAN user" }, 124 { NAP_PROFILE_ID, "PAN access point" }, 125 { GN_PROFILE_ID, "PAN group network" }, 126 { HID_SVCLASS_ID, "Human Interface Device" }, 127 { CIP_SVCLASS_ID, "Common ISDN Access" }, 128 { 0 } 129}; 130 131static char *string_lookup(struct tupla *pt0, int index) 132{ 133 struct tupla *pt; 134 for (pt = pt0; pt->index; pt++) 135 if (pt->index == index) 136 return pt->str; 137 return ""; 138} 139 140/* 141 * Prints into a string the Protocol UUID 142 * coping a maximum of n characters. 143 */ 144static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n) 145{ 146 char *str2; 147 148 if (!uuid) { 149 snprintf(str, n, "NULL"); 150 return -2; 151 } 152 switch (uuid->type) { 153 case SDP_UUID16: 154 str2 = string_lookup(message, uuid->value.uuid16); 155 snprintf(str, n, str2); 156 break; 157 case SDP_UUID32: 158 snprintf(str, n, "Error: This is uuid32"); 159 return -3; 160 case SDP_UUID128: 161 snprintf(str, n, "Error: This is uuid128"); 162 return -4; 163 default: 164 snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type); 165 return -1; 166 } 167 return 0; 168} 169 170int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n) 171{ 172 return uuid2str(Protocol, uuid, str, n); 173} 174 175int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n) 176{ 177 return uuid2str(ServiceClass, uuid, str, n); 178} 179 180int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n) 181{ 182 return uuid2str(Profile, uuid, str, n); 183} 184 185/* 186 * convert the UUID to string, copying a maximum of n characters. 187 */ 188int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n) 189{ 190 if (!uuid) { 191 snprintf(str, n, "NULL"); 192 return -2; 193 } 194 switch (uuid->type) { 195 case SDP_UUID16: 196 snprintf(str, n, "%.4x", uuid->value.uuid16); 197 break; 198 case SDP_UUID32: 199 snprintf(str, n, "%.8x", uuid->value.uuid32); 200 break; 201 case SDP_UUID128:{ 202 unsigned int data0; 203 unsigned short data1; 204 unsigned short data2; 205 unsigned short data3; 206 unsigned int data4; 207 unsigned short data5; 208 209 memcpy(&data0, &uuid->value.uuid128.data[0], 4); 210 memcpy(&data1, &uuid->value.uuid128.data[4], 2); 211 memcpy(&data2, &uuid->value.uuid128.data[6], 2); 212 memcpy(&data3, &uuid->value.uuid128.data[8], 2); 213 memcpy(&data4, &uuid->value.uuid128.data[10], 4); 214 memcpy(&data5, &uuid->value.uuid128.data[14], 2); 215 216 snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", 217 ntohl(data0), ntohs(data1), 218 ntohs(data2), ntohs(data3), 219 ntohl(data4), ntohs(data5)); 220 } 221 break; 222 default: 223 snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type); 224 return -1; // Enum type of UUID not set 225 } 226 return 0; 227} 228 229#ifdef SDP_DEBUG 230/* 231 * Function prints the UUID in hex as per defined syntax - 232 * 233 * 4bytes-2bytes-2bytes-2bytes-6bytes 234 * 235 * There is some ugly code, including hardcoding, but 236 * that is just the way it is converting 16 and 32 bit 237 * UUIDs to 128 bit as defined in the SDP doc 238 */ 239void sdp_uuid_print(const uuid_t *uuid) 240{ 241 if (uuid == NULL) { 242 SDPERR("Null passed to print UUID\n"); 243 return; 244 } 245 if (uuid->type == SDP_UUID16) { 246 SDPDBG(" uint16_t : 0x%.4x\n", uuid->value.uuid16); 247 } else if (uuid->type == SDP_UUID32) { 248 SDPDBG(" uint32_t : 0x%.8x\n", uuid->value.uuid32); 249 } else if (uuid->type == SDP_UUID128) { 250 unsigned int data0; 251 unsigned short data1; 252 unsigned short data2; 253 unsigned short data3; 254 unsigned int data4; 255 unsigned short data5; 256 257 memcpy(&data0, &uuid->value.uuid128.data[0], 4); 258 memcpy(&data1, &uuid->value.uuid128.data[4], 2); 259 memcpy(&data2, &uuid->value.uuid128.data[6], 2); 260 memcpy(&data3, &uuid->value.uuid128.data[8], 2); 261 memcpy(&data4, &uuid->value.uuid128.data[10], 4); 262 memcpy(&data5, &uuid->value.uuid128.data[14], 2); 263 264 SDPDBG(" uint128_t : 0x%.8x-", ntohl(data0)); 265 SDPDBG("%.4x-", ntohs(data1)); 266 SDPDBG("%.4x-", ntohs(data2)); 267 SDPDBG("%.4x-", ntohs(data3)); 268 SDPDBG("%.8x", ntohl(data4)); 269 SDPDBG("%.4x\n", ntohs(data5)); 270 } else 271 SDPERR("Enum type of UUID not set\n"); 272} 273#endif 274 275sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value) 276{ 277 sdp_data_t *seq; 278 int len = 0; 279 sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t)); 280 281 if (!d) 282 return NULL; 283 284 memset(d, 0, sizeof(sdp_data_t)); 285 d->dtd = dtd; 286 d->unitSize = sizeof(uint8_t); 287 288 switch (dtd) { 289 case SDP_DATA_NIL: 290 break; 291 case SDP_UINT8: 292 d->val.uint8 = *(uint8_t *)value; 293 d->unitSize += sizeof(uint8_t); 294 break; 295 case SDP_INT8: 296 case SDP_BOOL: 297 d->val.int8 = *(int8_t *)value; 298 d->unitSize += sizeof(int8_t); 299 break; 300 case SDP_UINT16: 301 d->val.uint16 = sdp_get_unaligned((uint16_t *)value); 302 d->unitSize += sizeof(uint16_t); 303 break; 304 case SDP_INT16: 305 d->val.int16 = sdp_get_unaligned((int16_t *)value); 306 d->unitSize += sizeof(int16_t); 307 break; 308 case SDP_UINT32: 309 d->val.uint32 = sdp_get_unaligned((uint32_t *)value); 310 d->unitSize += sizeof(uint32_t); 311 break; 312 case SDP_INT32: 313 d->val.int32 = sdp_get_unaligned((int32_t *)value); 314 d->unitSize += sizeof(int32_t); 315 break; 316 case SDP_INT64: 317 d->val.int64 = sdp_get_unaligned((int64_t *)value); 318 d->unitSize += sizeof(int64_t); 319 break; 320 case SDP_UINT64: 321 d->val.uint64 = sdp_get_unaligned((uint64_t *)value); 322 d->unitSize += sizeof(uint64_t); 323 break; 324 case SDP_UINT128: 325 memcpy(&d->val.uint128.data, value, sizeof(uint128_t)); 326 d->unitSize += sizeof(uint128_t); 327 break; 328 case SDP_INT128: 329 memcpy(&d->val.int128.data, value, sizeof(uint128_t)); 330 d->unitSize += sizeof(uint128_t); 331 break; 332 case SDP_UUID16: 333 sdp_uuid16_create(&d->val.uuid, sdp_get_unaligned((uint16_t *)value)); 334 d->unitSize += sizeof(uint16_t); 335 break; 336 case SDP_UUID32: 337 sdp_uuid32_create(&d->val.uuid, sdp_get_unaligned((uint32_t *)value)); 338 d->unitSize += sizeof(uint32_t); 339 break; 340 case SDP_UUID128: 341 sdp_uuid128_create(&d->val.uuid, value); 342 d->unitSize += sizeof(uint128_t); 343 break; 344 case SDP_URL_STR8: 345 case SDP_TEXT_STR8: 346 case SDP_URL_STR16: 347 case SDP_TEXT_STR16: 348 if (!value) 349 goto out_error; 350 351 len = strlen(value); 352 d->unitSize += len; 353 if (len <= USHRT_MAX) { 354 d->val.str = (char *)malloc(len + 1); 355 if (!d->val.str) 356 goto out_error; 357 358 strcpy(d->val.str, value); 359 if (len <= UCHAR_MAX) { 360 d->unitSize += sizeof(uint8_t); 361 if (dtd != SDP_URL_STR8 && dtd != SDP_TEXT_STR8) { 362 if (dtd == SDP_URL_STR16) 363 dtd = SDP_URL_STR8; 364 else 365 dtd = SDP_TEXT_STR8; 366 } 367 } else { 368 d->unitSize += sizeof(uint16_t); 369 if (dtd == SDP_TEXT_STR8) 370 dtd = SDP_TEXT_STR16; 371 else 372 dtd = SDP_URL_STR16; 373 } 374 } else { 375 SDPERR("Strings of size > USHRT_MAX not supported\n"); 376 goto out_error; 377 } 378 break; 379 case SDP_URL_STR32: 380 case SDP_TEXT_STR32: 381 SDPERR("Strings of size > USHRT_MAX not supported\n"); 382 break; 383 case SDP_ALT8: 384 case SDP_ALT16: 385 case SDP_ALT32: 386 case SDP_SEQ8: 387 case SDP_SEQ16: 388 case SDP_SEQ32: 389 if (dtd == SDP_ALT8 || dtd == SDP_SEQ8) 390 d->unitSize += sizeof(uint8_t); 391 else if (dtd == SDP_ALT16 || dtd == SDP_SEQ16) 392 d->unitSize += sizeof(uint16_t); 393 else if (dtd == SDP_ALT32 || dtd == SDP_SEQ32) 394 d->unitSize += sizeof(uint32_t); 395 seq = (sdp_data_t *)value; 396 d->val.dataseq = seq; 397 for (; seq; seq = seq->next) 398 d->unitSize += seq->unitSize; 399 break; 400 default: 401 goto out_error; 402 } 403 return d; 404 405out_error: 406 free(d); 407 return NULL; 408} 409 410sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *d) 411{ 412 if (seq) { 413 sdp_data_t *p; 414 for (p = seq; p->next; p = p->next); 415 p->next = d; 416 } else 417 seq = d; 418 d->next = NULL; 419 return seq; 420} 421 422sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len) 423{ 424 sdp_data_t *curr = NULL, *seq = NULL; 425 int i; 426 427 for (i = 0; i < len; i++) { 428 sdp_data_t *data; 429 uint8_t dtd = *(uint8_t *)dtds[i]; 430 if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32) 431 data = (sdp_data_t *)values[i]; 432 else 433 data = sdp_data_alloc(dtd, values[i]); 434 if (!data) 435 return NULL; 436 if (curr) 437 curr->next = data; 438 else 439 seq = data; 440 curr = data; 441 } 442 return sdp_data_alloc(SDP_SEQ8, seq); 443} 444 445int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d) 446{ 447 sdp_data_t *p = sdp_data_get(rec, attr); 448 449 if (p) 450 return -1; 451 d->attrId = attr; 452 rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func); 453 return 0; 454} 455 456void sdp_attr_remove(sdp_record_t *rec, uint16_t attr) 457{ 458 sdp_data_t *d = sdp_data_get(rec, attr); 459 if (d) 460 rec->attrlist = sdp_list_remove(rec->attrlist, d); 461} 462 463void sdp_set_seq_len(char *ptr, int length) 464{ 465 uint8_t dtd = *(uint8_t *)ptr++; 466 467 switch (dtd) { 468 case SDP_SEQ8: 469 case SDP_ALT8: 470 case SDP_TEXT_STR8: 471 case SDP_URL_STR8: 472 *(uint8_t *)ptr = (uint8_t)length; 473 break; 474 case SDP_SEQ16: 475 case SDP_ALT16: 476 case SDP_TEXT_STR16: 477 case SDP_URL_STR16: 478 sdp_put_unaligned(htons(length), (uint16_t *)ptr); 479 break; 480 case SDP_SEQ32: 481 case SDP_ALT32: 482 case SDP_TEXT_STR32: 483 case SDP_URL_STR32: 484 sdp_put_unaligned(htons(length), (uint32_t *)ptr); 485 break; 486 } 487} 488 489int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd) 490{ 491 int orig = buf->data_size; 492 uint8_t *p = buf->data + buf->data_size; 493 494 *p++ = dtd; 495 buf->data_size += sizeof(uint8_t); 496 switch (dtd) { 497 case SDP_SEQ8: 498 case SDP_TEXT_STR8: 499 case SDP_URL_STR8: 500 case SDP_ALT8: 501 buf->data_size += sizeof(uint8_t); 502 break; 503 case SDP_SEQ16: 504 case SDP_TEXT_STR16: 505 case SDP_URL_STR16: 506 case SDP_ALT16: 507 buf->data_size += sizeof(uint16_t); 508 break; 509 case SDP_SEQ32: 510 case SDP_TEXT_STR32: 511 case SDP_URL_STR32: 512 case SDP_ALT32: 513 buf->data_size += sizeof(uint32_t); 514 break; 515 } 516 return buf->data_size - orig; 517} 518 519void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr) 520{ 521 uint8_t *p = buf->data; 522 523 // data type for attr 524 *p++ = SDP_UINT16; 525 buf->data_size = sizeof(uint8_t); 526 sdp_put_unaligned(htons(attr), (uint16_t *)p); 527 p += sizeof(uint16_t); 528 buf->data_size += sizeof(uint16_t); 529} 530 531static int get_data_size(sdp_buf_t *buf, sdp_data_t *sdpdata) 532{ 533 sdp_data_t *d; 534 int n = 0; 535 536 for (d = sdpdata->val.dataseq; d; d = d->next) 537 n += sdp_gen_pdu(buf, d); 538 return n; 539} 540 541int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d) 542{ 543 int pdu_size = 0, data_size = 0; 544 unsigned char *src = NULL, is_seq = 0, is_alt = 0; 545 uint8_t dtd = d->dtd; 546 uint16_t u16; 547 uint32_t u32; 548 uint64_t u64; 549 uint128_t u128; 550 char *seqp = buf->data + buf->data_size; 551 552 pdu_size = sdp_set_data_type(buf, dtd); 553 switch (dtd) { 554 case SDP_DATA_NIL: 555 break; 556 case SDP_UINT8: 557 src = &d->val.uint8; 558 data_size = sizeof(uint8_t); 559 break; 560 case SDP_UINT16: 561 u16 = htons(d->val.uint16); 562 src = (unsigned char *)&u16; 563 data_size = sizeof(uint16_t); 564 break; 565 case SDP_UINT32: 566 u32 = htonl(d->val.uint32); 567 src = (unsigned char *)&u32; 568 data_size = sizeof(uint32_t); 569 break; 570 case SDP_UINT64: 571 u64 = hton64(d->val.uint64); 572 src = (unsigned char *)&u64; 573 data_size = sizeof(uint64_t); 574 break; 575 case SDP_UINT128: 576 hton128(&d->val.uint128, &u128); 577 src = (unsigned char *)&u128; 578 data_size = sizeof(uint128_t); 579 break; 580 case SDP_INT8: 581 case SDP_BOOL: 582 src = (unsigned char *)&d->val.int8; 583 data_size = sizeof(int8_t); 584 break; 585 case SDP_INT16: 586 u16 = htons(d->val.int16); 587 src = (unsigned char *)&u16; 588 data_size = sizeof(int16_t); 589 break; 590 case SDP_INT32: 591 u32 = htonl(d->val.int32); 592 src = (unsigned char *)&u32; 593 data_size = sizeof(int32_t); 594 break; 595 case SDP_INT64: 596 u64 = hton64(d->val.int64); 597 src = (unsigned char *)&u64; 598 data_size = sizeof(int64_t); 599 break; 600 case SDP_INT128: 601 hton128(&d->val.int128, &u128); 602 src = (unsigned char *)&u128; 603 data_size = sizeof(uint128_t); 604 break; 605 case SDP_TEXT_STR8: 606 case SDP_URL_STR8: 607 case SDP_TEXT_STR16: 608 case SDP_TEXT_STR32: 609 case SDP_URL_STR16: 610 case SDP_URL_STR32: 611 src = (unsigned char *)d->val.str; 612 data_size = strlen(d->val.str); 613 sdp_set_seq_len(seqp, data_size); 614 break; 615 case SDP_SEQ8: 616 case SDP_SEQ16: 617 case SDP_SEQ32: 618 is_seq = 1; 619 data_size = get_data_size(buf, d); 620 sdp_set_seq_len(seqp, data_size); 621 break; 622 case SDP_ALT8: 623 case SDP_ALT16: 624 case SDP_ALT32: 625 is_alt = 1; 626 data_size = get_data_size(buf, d); 627 sdp_set_seq_len(seqp, data_size); 628 break; 629 case SDP_UUID16: 630 u16 = htons(d->val.uuid.value.uuid16); 631 src = (unsigned char *)&u16; 632 data_size = sizeof(uint16_t); 633 break; 634 case SDP_UUID32: 635 u32 = htonl(d->val.uuid.value.uuid32); 636 src = (unsigned char *)&u32; 637 data_size = sizeof(uint32_t); 638 break; 639 case SDP_UUID128: 640 src = (unsigned char *)&d->val.uuid.value.uuid128; 641 data_size = sizeof(uint128_t); 642 break; 643 default: 644 break; 645 } 646 if (!is_seq && !is_alt) { 647 if (src && buf) { 648 memcpy(buf->data + buf->data_size, src, data_size); 649 buf->data_size += data_size; 650 } else if (dtd != SDP_DATA_NIL) 651 SDPDBG("Gen PDU : Cant copy from NULL source or dest\n"); 652 } 653 pdu_size += data_size; 654 return pdu_size; 655} 656 657static void sdp_attr_pdu(void *value, void *udata) 658{ 659 sdp_append_to_pdu((sdp_buf_t *)udata, (sdp_data_t *)value); 660} 661 662int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *buf) 663{ 664 buf->data = (char *)malloc(SDP_PDU_CHUNK_SIZE); 665 if (buf->data) { 666 buf->buf_size = SDP_PDU_CHUNK_SIZE; 667 buf->data_size = 0; 668 memset(buf->data, 0, buf->buf_size); 669 sdp_list_foreach(rec->attrlist, sdp_attr_pdu, buf); 670 return 0; 671 } 672 return -1; 673} 674 675void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *d) 676{ 677 sdp_data_t *p = sdp_data_get(rec, attr); 678 679 if (p) { 680 rec->attrlist = sdp_list_remove(rec->attrlist, p); 681 sdp_data_free(p); 682 } 683 d->attrId = attr; 684 rec->attrlist = sdp_list_insert_sorted(rec->attrlist, (void *)d, sdp_attrid_comp_func); 685} 686 687int sdp_attrid_comp_func(const void *key1, const void *key2) 688{ 689 const sdp_data_t *d1 = (const sdp_data_t *)key1; 690 const sdp_data_t *d2 = (const sdp_data_t *)key2; 691 692 if (d1 && d2) 693 return d1->attrId - d2->attrId; 694 return 0; 695} 696 697static void data_seq_free(sdp_data_t *seq) 698{ 699 sdp_data_t *d = seq->val.dataseq; 700 701 while (d) { 702 sdp_data_t *next = d->next; 703 sdp_data_free(d); 704 d = next; 705 } 706} 707 708void sdp_data_free(sdp_data_t *d) 709{ 710 switch (d->dtd) { 711 case SDP_SEQ8: 712 case SDP_SEQ16: 713 case SDP_SEQ32: 714 data_seq_free(d); 715 break; 716 case SDP_URL_STR8: 717 case SDP_URL_STR16: 718 case SDP_URL_STR32: 719 case SDP_TEXT_STR8: 720 case SDP_TEXT_STR16: 721 case SDP_TEXT_STR32: 722 free(d->val.str); 723 break; 724 } 725 free(d); 726} 727 728static sdp_data_t *extract_int(const void *p, int *len) 729{ 730 sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t)); 731 732 SDPDBG("Extracting integer\n"); 733 memset(d, 0, sizeof(sdp_data_t)); 734 d->dtd = *(uint8_t *)p; 735 p += sizeof(uint8_t); 736 *len += sizeof(uint8_t); 737 738 switch (d->dtd) { 739 case SDP_DATA_NIL: 740 break; 741 case SDP_BOOL: 742 case SDP_INT8: 743 case SDP_UINT8: 744 *len += sizeof(uint8_t); 745 d->val.uint8 = *(uint8_t *)p; 746 break; 747 case SDP_INT16: 748 case SDP_UINT16: 749 *len += sizeof(uint16_t); 750 d->val.uint16 = ntohs(sdp_get_unaligned((uint16_t *)p)); 751 break; 752 case SDP_INT32: 753 case SDP_UINT32: 754 *len += sizeof(uint32_t); 755 d->val.uint32 = ntohl(sdp_get_unaligned((uint32_t *)p)); 756 break; 757 case SDP_INT64: 758 case SDP_UINT64: 759 *len += sizeof(uint64_t); 760 d->val.uint64 = ntoh64(sdp_get_unaligned((uint64_t *)p)); 761 break; 762 case SDP_INT128: 763 case SDP_UINT128: 764 *len += sizeof(uint128_t); 765 ntoh128((uint128_t *)p, &d->val.uint128); 766 break; 767 default: 768 free(d); 769 d = NULL; 770 } 771 return d; 772} 773 774static sdp_data_t *extract_uuid(const void *p, int *len, sdp_record_t *rec) 775{ 776 sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t)); 777 778 SDPDBG("Extracting UUID"); 779 memset(d, 0, sizeof(sdp_data_t)); 780 if (0 > sdp_uuid_extract(p, &d->val.uuid, len)) { 781 free(d); 782 return NULL; 783 } 784 d->dtd = *(uint8_t *)p; 785 sdp_pattern_add_uuid(rec, &d->val.uuid); 786 return d; 787} 788 789/* 790 * Extract strings from the PDU (could be service description and similar info) 791 */ 792static sdp_data_t *extract_str(const void *p, int *len) 793{ 794 char *s; 795 int n; 796 sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t)); 797 798 memset(d, 0, sizeof(sdp_data_t)); 799 d->dtd = *(uint8_t *)p; 800 p += sizeof(uint8_t); 801 *len += sizeof(uint8_t); 802 803 switch (d->dtd) { 804 case SDP_TEXT_STR8: 805 case SDP_URL_STR8: 806 n = *(uint8_t *)p; 807 p += sizeof(uint8_t); 808 *len += sizeof(uint8_t) + n; 809 break; 810 case SDP_TEXT_STR16: 811 case SDP_URL_STR16: 812 n = ntohs(sdp_get_unaligned((uint16_t *)p)); 813 p += sizeof(uint16_t); 814 *len += sizeof(uint16_t) + n; 815 break; 816 default: 817 SDPERR("Sizeof text string > UINT16_MAX\n"); 818 free(d); 819 return 0; 820 } 821 822 s = malloc(n + 1); 823 memset(s, 0, n + 1); 824 memcpy(s, p, n); 825 826 SDPDBG("Len : %d\n", n); 827 SDPDBG("Str : %s\n", s); 828 829 d->val.str = s; 830 d->unitSize = n; 831 return d; 832} 833 834static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec) 835{ 836 int seqlen, n = 0; 837 sdp_data_t *curr, *prev; 838 sdp_data_t *d = (sdp_data_t *)malloc(sizeof(sdp_data_t)); 839 840 SDPDBG("Extracting SEQ"); 841 memset(d, 0, sizeof(sdp_data_t)); 842 *len = sdp_extract_seqtype(p, &d->dtd, &seqlen); 843 SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen); 844 845 if (*len == 0) 846 return d; 847 848 p += *len; 849 curr = prev = NULL; 850 while (n < seqlen) { 851 int attrlen = 0; 852 curr = sdp_extract_attr(p, &attrlen, rec); 853 if (curr == NULL) 854 break; 855 856 if (prev) 857 prev->next = curr; 858 else 859 d->val.dataseq = curr; 860 prev = curr; 861 p += attrlen; 862 n += attrlen; 863 864 SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen); 865 } 866 867 *len += n; 868 return d; 869} 870 871sdp_data_t *sdp_extract_attr(const char *p, int *size, sdp_record_t *rec) 872{ 873 sdp_data_t *elem; 874 int n = 0; 875 uint8_t dtd = *(const uint8_t *)p; 876 877 SDPDBG("extract_attr: dtd=0x%x", dtd); 878 switch (dtd) { 879 case SDP_DATA_NIL: 880 case SDP_BOOL: 881 case SDP_UINT8: 882 case SDP_UINT16: 883 case SDP_UINT32: 884 case SDP_UINT64: 885 case SDP_UINT128: 886 case SDP_INT8: 887 case SDP_INT16: 888 case SDP_INT32: 889 case SDP_INT64: 890 case SDP_INT128: 891 elem = extract_int(p, &n); 892 break; 893 case SDP_UUID16: 894 case SDP_UUID32: 895 case SDP_UUID128: 896 elem = extract_uuid(p, &n, rec); 897 break; 898 case SDP_TEXT_STR8: 899 case SDP_TEXT_STR16: 900 case SDP_TEXT_STR32: 901 case SDP_URL_STR8: 902 case SDP_URL_STR16: 903 case SDP_URL_STR32: 904 elem = extract_str(p, &n); 905 break; 906 case SDP_SEQ8: 907 case SDP_SEQ16: 908 case SDP_SEQ32: 909 case SDP_ALT8: 910 case SDP_ALT16: 911 case SDP_ALT32: 912 elem = extract_seq(p, &n, rec); 913 break; 914 default: 915 SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd); 916 return NULL; 917 } 918 *size += n; 919 return elem; 920} 921 922#ifdef SDP_DEBUG 923static void attr_print_func(void *value, void *userData) 924{ 925 sdp_data_t *d = (sdp_data_t *)value; 926 927 SDPDBG("=====================================\n"); 928 SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n", d->attrId); 929 SDPDBG("ATTRIBUTE VALUE PTR : 0x%x\n", (uint32_t)value); 930 if (d) 931 sdp_data_print(d); 932 else 933 SDPDBG("NULL value\n"); 934 SDPDBG("=====================================\n"); 935} 936 937void sdp_print_service_attr(sdp_list_t *svcAttrList) 938{ 939 sdp_list_foreach(svcAttrList, attr_print_func, NULL); 940} 941#endif 942 943sdp_record_t *sdp_extract_pdu(const char *buf, int *scanned) 944{ 945 int extracted = 0, seqlen = 0; 946 uint8_t dtd; 947 uint16_t attr; 948 sdp_record_t *rec = sdp_record_alloc(); 949 const char *p = buf; 950 951 *scanned = sdp_extract_seqtype(buf, &dtd, &seqlen); 952 p += *scanned; 953 rec->attrlist = NULL; 954 while (extracted < seqlen) { 955 int n = sizeof(uint8_t), attrlen = 0; 956 sdp_data_t *data = NULL; 957 958 SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, extracted); 959 dtd = *(uint8_t *)p; 960 attr = ntohs(sdp_get_unaligned((uint16_t *)(p+n))); 961 n += sizeof(uint16_t); 962 963 SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr); 964 965 data = sdp_extract_attr(p+n, &attrlen, rec); 966 967 SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen); 968 969 n += attrlen; 970 if (data == NULL) { 971 SDPDBG("Terminating extraction of attributes"); 972 break; 973 } 974 if (attr == SDP_ATTR_RECORD_HANDLE) 975 rec->handle = data->val.uint32; 976 extracted += n; 977 p += n; 978 sdp_attr_replace(rec, attr, data); 979 SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d", 980 seqlen, extracted); 981 } 982#ifdef SDP_DEBUG 983 SDPDBG("Successful extracting of Svc Rec attributes\n"); 984 sdp_print_service_attr(rec->attrlist); 985#endif 986 *scanned += seqlen; 987 return rec; 988} 989 990#ifdef SDP_DEBUG 991static void print_dataseq(sdp_data_t *p) 992{ 993 sdp_data_t *d; 994 995 for (d = p; d; d = d->next) 996 sdp_data_print(d); 997} 998#endif 999 1000void sdp_record_print(const sdp_record_t *rec) 1001{ 1002 sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); 1003 if (d) 1004 printf("Service Name: %s\n", d->val.str); 1005 d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY); 1006 if (d) 1007 printf("Service Description: %s\n", d->val.str); 1008 d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY); 1009 if (d) 1010 printf("Service Provider: %s\n", d->val.str); 1011} 1012 1013#ifdef SDP_DEBUG 1014void sdp_data_print(sdp_data_t *d) 1015{ 1016 switch (d->dtd) { 1017 case SDP_DATA_NIL: 1018 SDPDBG("NIL\n"); 1019 break; 1020 case SDP_BOOL: 1021 case SDP_UINT8: 1022 case SDP_UINT16: 1023 case SDP_UINT32: 1024 case SDP_UINT64: 1025 case SDP_UINT128: 1026 case SDP_INT8: 1027 case SDP_INT16: 1028 case SDP_INT32: 1029 case SDP_INT64: 1030 case SDP_INT128: 1031 SDPDBG("Integer : 0x%x\n", d->val.uint32); 1032 break; 1033 case SDP_UUID16: 1034 case SDP_UUID32: 1035 case SDP_UUID128: 1036 SDPDBG("UUID\n"); 1037 sdp_uuid_print(&d->val.uuid); 1038 break; 1039 case SDP_TEXT_STR8: 1040 case SDP_TEXT_STR16: 1041 case SDP_TEXT_STR32: 1042 SDPDBG("Text : %s\n", d->val.str); 1043 break; 1044 case SDP_URL_STR8: 1045 case SDP_URL_STR16: 1046 case SDP_URL_STR32: 1047 SDPDBG("URL : %s\n", d->val.str); 1048 break; 1049 case SDP_SEQ8: 1050 case SDP_SEQ16: 1051 case SDP_SEQ32: 1052 print_dataseq(d->val.dataseq); 1053 break; 1054 case SDP_ALT8: 1055 case SDP_ALT16: 1056 case SDP_ALT32: 1057 SDPDBG("Data Sequence Alternates\n"); 1058 print_dataseq(d->val.dataseq); 1059 break; 1060 } 1061} 1062#endif 1063 1064sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId) 1065{ 1066 if (rec->attrlist) { 1067 sdp_data_t sdpTemplate; 1068 sdp_list_t *p; 1069 1070 sdpTemplate.attrId = attrId; 1071 p = sdp_list_find(rec->attrlist, &sdpTemplate, sdp_attrid_comp_func); 1072 if (p) 1073 return (sdp_data_t *)p->data; 1074 } 1075 return 0; 1076} 1077 1078/* 1079 * Extract the sequence type and its length, and return offset into buf 1080 * or 0 on failure. 1081 */ 1082int sdp_extract_seqtype(const char *buf, uint8_t *dtdp, int *size) 1083{ 1084 uint8_t dtd = *(uint8_t *)buf; 1085 int scanned = sizeof(uint8_t); 1086 1087 buf += sizeof(uint8_t); 1088 *dtdp = dtd; 1089 switch (dtd) { 1090 case SDP_SEQ8: 1091 case SDP_ALT8: 1092 *size = *(uint8_t *)buf; 1093 scanned += sizeof(uint8_t); 1094 break; 1095 case SDP_SEQ16: 1096 case SDP_ALT16: 1097 *size = ntohs(sdp_get_unaligned((uint16_t *)buf)); 1098 scanned += sizeof(uint16_t); 1099 break; 1100 case SDP_SEQ32: 1101 case SDP_ALT32: 1102 *size = ntohl(sdp_get_unaligned((uint32_t *)buf)); 1103 scanned += sizeof(uint32_t); 1104 break; 1105 default: 1106 SDPERR("Unknown sequence type, aborting\n"); 1107 return 0; 1108 } 1109 return scanned; 1110} 1111 1112int sdp_send_req(sdp_session_t *session, char *buf, int size) 1113{ 1114 int sent = 0; 1115 1116 while (sent < size) { 1117 int n = send(session->sock, buf + sent, size - sent, 0); 1118 if (n < 0) 1119 return -1; 1120 sent += n; 1121 } 1122 return 0; 1123} 1124 1125int sdp_read_rsp(sdp_session_t *session, char *buf, int size) 1126{ 1127 fd_set readFds; 1128 struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 }; 1129 1130 FD_SET(session->sock, &readFds); 1131 SDPDBG("Waiting for response\n"); 1132 if (0 == select(session->sock + 1, &readFds, NULL, NULL, &timeout)) { 1133 SDPERR("Client timed out\n"); 1134 errno = ETIMEDOUT; 1135 return -1; 1136 } 1137 return recv(session->sock, buf, size, 0); 1138} 1139 1140/* 1141 * generic send request, wait for response method. 1142 */ 1143int sdp_send_req_w4_rsp(sdp_session_t *session, char *reqbuf, char *rspbuf, int reqsize, int *rspsize) 1144{ 1145 int n; 1146 sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)reqbuf; 1147 sdp_pdu_hdr_t *rsphdr = (sdp_pdu_hdr_t *)rspbuf; 1148 1149 SDPDBG(""); 1150 if (0 > sdp_send_req(session, reqbuf, reqsize)) { 1151 SDPERR("Error sending data:%s", strerror(errno)); 1152 return -1; 1153 } 1154 n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); 1155 if (0 > n) 1156 return -1; 1157 SDPDBG("Read : %d\n", n); 1158 if (n == 0 || reqhdr->tid != rsphdr->tid) { 1159 errno = EPROTO; 1160 return -1; 1161 } 1162 *rspsize = n; 1163 return 0; 1164} 1165 1166/* 1167 * singly-linked lists (after openobex implementation) 1168 */ 1169sdp_list_t *sdp_list_append(sdp_list_t *p, void *d) 1170{ 1171 sdp_list_t *q, *n = (sdp_list_t *)malloc(sizeof(sdp_list_t)); 1172 1173 if (!n) 1174 return 0; 1175 1176 n->data = d; 1177 n->next = 0; 1178 1179 if (!p) 1180 return n; 1181 1182 for (q = p; q->next; q = q->next); 1183 q->next = n; 1184 1185 return p; 1186} 1187 1188sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d) 1189{ 1190 sdp_list_t *p, *q; 1191 1192 for (q = 0, p = list; p; q = p, p = p->next) 1193 if (p->data == d) { 1194 if (q) 1195 q->next = p->next; 1196 else 1197 list = p->next; 1198 free(p); 1199 break; 1200 } 1201 1202 return list; 1203} 1204 1205sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *d, sdp_comp_func_t f) 1206{ 1207 sdp_list_t *q, *p, *n; 1208 1209 n = (sdp_list_t *)malloc(sizeof(sdp_list_t)); 1210 if (!n) 1211 return 0; 1212 n->data = d; 1213 for (q = 0, p = list; p; q = p, p = p->next) 1214 if (f(p->data, d) >= 0) 1215 break; 1216 // insert between q and p; if !q insert at head 1217 if (q) 1218 q->next = n; 1219 else 1220 list = n; 1221 n->next = p; 1222 return list; 1223} 1224 1225/* 1226 * Every element of the list points to things which need 1227 * to be free()'d. This method frees the list's contents 1228 */ 1229void sdp_list_free(sdp_list_t *list, sdp_free_func_t f) 1230{ 1231 sdp_list_t *next; 1232 while (list) { 1233 next = list->next; 1234 if (f) 1235 f(list->data); 1236 free(list); 1237 list = next; 1238 } 1239} 1240 1241static inline int __find_port(sdp_data_t *seq, int proto) 1242{ 1243 if (!seq || !seq->next) 1244 return 0; 1245 1246 if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) { 1247 seq = seq->next; 1248 switch (seq->dtd) { 1249 case SDP_UINT8: 1250 return seq->val.uint8; 1251 case SDP_UINT16: 1252 return seq->val.uint16; 1253 } 1254 } 1255 return 0; 1256} 1257 1258int sdp_get_proto_port(const sdp_list_t *list, int proto) 1259{ 1260 if (proto != L2CAP_UUID && proto != RFCOMM_UUID) { 1261 errno = EINVAL; 1262 return -1; 1263 } 1264 1265 for (; list; list = list->next) { 1266 sdp_list_t *p; 1267 for (p = list->data; p; p = p->next) { 1268 sdp_data_t *seq = (sdp_data_t *) p->data; 1269 int port = __find_port(seq, proto); 1270 if (port) 1271 return port; 1272 } 1273 } 1274 return 0; 1275} 1276 1277sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto) 1278{ 1279 for (; list; list = list->next) { 1280 sdp_list_t *p; 1281 for (p = list->data; p; p = p->next) { 1282 sdp_data_t *seq = (sdp_data_t *) p->data; 1283 if (SDP_IS_UUID(seq->dtd) && 1284 sdp_uuid_to_proto(&seq->val.uuid) == proto) 1285 return seq->next; 1286 } 1287 } 1288 return NULL; 1289} 1290 1291int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap) 1292{ 1293 sdp_data_t *pdlist, *curr; 1294 sdp_list_t *ap = 0; 1295 1296 pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST); 1297 if (pdlist == NULL) { 1298 errno = ENODATA; 1299 return -1; 1300 } 1301 SDPDBG("AP type : 0%x\n", pdlist->dtd); 1302 1303 for (; pdlist; pdlist = pdlist->next) { 1304 sdp_list_t *pds = 0; 1305 for (curr = pdlist->val.dataseq; curr; curr = curr->next) 1306 pds = sdp_list_append(pds, curr->val.dataseq); 1307 ap = sdp_list_append(ap, pds); 1308 } 1309 *pap = ap; 1310 return 0; 1311} 1312 1313int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap) 1314{ 1315 sdp_data_t *pdlist, *curr; 1316 sdp_list_t *ap = 0; 1317 1318 pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); 1319 if (pdlist == NULL) { 1320 errno = ENODATA; 1321 return -1; 1322 } 1323 SDPDBG("AP type : 0%x\n", pdlist->dtd); 1324 1325 pdlist = pdlist->val.dataseq; 1326 1327 for (; pdlist; pdlist = pdlist->next) { 1328 sdp_list_t *pds = 0; 1329 for (curr = pdlist->val.dataseq; curr; curr = curr->next) 1330 pds = sdp_list_append(pds, curr->val.dataseq); 1331 ap = sdp_list_append(ap, pds); 1332 } 1333 *pap = ap; 1334 return 0; 1335} 1336 1337int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp) 1338{ 1339 sdp_data_t *sdpdata = sdp_data_get(rec, attr); 1340 1341 *seqp = NULL; 1342 if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) { 1343 sdp_data_t *d; 1344 for (d = sdpdata->val.dataseq; d; d = d->next) { 1345 uuid_t *u = (uuid_t *)malloc(sizeof(uuid_t)); 1346 memset((char *)u, 0, sizeof(uuid_t)); 1347 if (d->dtd >= SDP_UUID16 && d->dtd <= SDP_UUID128) { 1348 *u = d->val.uuid; 1349 *seqp = sdp_list_append(*seqp, u); 1350 } else 1351 goto fail; 1352 } 1353 return 0; 1354 } 1355fail: 1356 sdp_list_free(*seqp, free); 1357 errno = EINVAL; 1358 return -1; 1359} 1360 1361int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq) 1362{ 1363 int status = 0, i, len; 1364 void **dtds, **values; 1365 uint8_t uuid16 = SDP_UUID16; 1366 uint8_t uuid32 = SDP_UUID32; 1367 uint8_t uuid128 = SDP_UUID128; 1368 sdp_list_t *p; 1369 1370 len = sdp_list_len(seq); 1371 if (!seq || len == 0) 1372 return -1; 1373 dtds = (void **)malloc(len * sizeof(void *)); 1374 values = (void **)malloc(len * sizeof(void *)); 1375 for (p = seq, i = 0; i < len; i++, p = p->next) { 1376 uuid_t *uuid = (uuid_t *)p->data; 1377 if (uuid) 1378 switch (uuid->type) { 1379 case SDP_UUID16: 1380 dtds[i] = &uuid16; 1381 values[i] = &uuid->value.uuid16; 1382 break; 1383 case SDP_UUID32: 1384 dtds[i] = &uuid32; 1385 values[i] = &uuid->value.uuid32; 1386 break; 1387 case SDP_UUID128: 1388 dtds[i] = &uuid128; 1389 values[i] = &uuid->value.uuid128; 1390 break; 1391 default: 1392 status = -1; 1393 break; 1394 } 1395 else { 1396 status = -1; 1397 break; 1398 } 1399 } 1400 if (status == 0) { 1401 sdp_data_t *data = sdp_seq_alloc(dtds, values, len); 1402 sdp_attr_replace(rec, aid, data); 1403 sdp_pattern_add_uuidseq(rec, seq); 1404 } 1405 free(dtds); 1406 free(values); 1407 return status; 1408} 1409 1410int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq) 1411{ 1412 sdp_lang_attr_t *lang; 1413 sdp_data_t *sdpdata, *curr_data; 1414 1415 *langSeq = NULL; 1416 sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST); 1417 if (sdpdata == NULL) { 1418 errno = ENODATA; 1419 return -1; 1420 } 1421 curr_data = sdpdata->val.dataseq; 1422 while (curr_data) { 1423 sdp_data_t *pCode = curr_data; 1424 sdp_data_t *pEncoding = pCode->next; 1425 sdp_data_t *pOffset = pEncoding->next; 1426 if (pCode && pEncoding && pOffset) { 1427 lang = (sdp_lang_attr_t *)malloc(sizeof(sdp_lang_attr_t)); 1428 lang->code_ISO639 = pCode->val.uint16; 1429 lang->encoding = pEncoding->val.uint16; 1430 lang->base_offset = pOffset->val.uint16; 1431 SDPDBG("code_ISO639 : 0x%02x\n", lang->code_ISO639); 1432 SDPDBG("encoding : 0x%02x\n", lang->encoding); 1433 SDPDBG("base_offfset : 0x%02x\n", lang->base_offset); 1434 *langSeq = sdp_list_append(*langSeq, lang); 1435 } 1436 curr_data = pOffset->next; 1437 } 1438 return 0; 1439} 1440 1441int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) 1442{ 1443 sdp_profile_desc_t *profDesc; 1444 sdp_data_t *sdpdata, *seq; 1445 1446 *profDescSeq = NULL; 1447 sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST); 1448 if (!sdpdata || !sdpdata->val.dataseq) { 1449 errno = ENODATA; 1450 return -1; 1451 } 1452 for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) { 1453 sdp_data_t *uuid = seq->val.dataseq; 1454 sdp_data_t *pVnum = seq->val.dataseq->next; 1455 if (uuid && pVnum) { 1456 profDesc = (sdp_profile_desc_t *)malloc(sizeof(sdp_profile_desc_t)); 1457 profDesc->uuid = uuid->val.uuid; 1458 profDesc->version = pVnum->val.uint16; 1459#ifdef SDP_DEBUG 1460 sdp_uuid_print(&profDesc->uuid); 1461 SDPDBG("Vnum : 0x%04x\n", profDesc->version); 1462#endif 1463 *profDescSeq = sdp_list_append(*profDescSeq, profDesc); 1464 } 1465 } 1466 return 0; 1467} 1468 1469int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16) 1470{ 1471 sdp_data_t *d, *curr; 1472 1473 *u16 = NULL; 1474 d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST); 1475 if (d == NULL) { 1476 errno = ENODATA; 1477 return -1; 1478 } 1479 for (curr = d->val.dataseq; curr; curr = curr->next) 1480 *u16 = sdp_list_append(*u16, &curr->val.uint16); 1481 return 0; 1482} 1483 1484/* flexible extraction of basic attributes - Jean II */ 1485/* How do we expect caller to extract predefined data sequences? */ 1486int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value) 1487{ 1488 sdp_data_t *sdpdata = sdp_data_get(rec, attrid); 1489 1490 if (sdpdata) 1491 /* Verify that it is what the caller expects */ 1492 if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 || 1493 sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 || 1494 sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 || 1495 sdpdata->dtd == SDP_INT32) { 1496 *value = sdpdata->val.uint32; 1497 return 0; 1498 } 1499 errno = EINVAL; 1500 return -1; 1501} 1502 1503int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, int valuelen) 1504{ 1505 sdp_data_t *sdpdata = sdp_data_get(rec, attrid); 1506 if (sdpdata) 1507 /* Verify that it is what the caller expects */ 1508 if (sdpdata->dtd == SDP_TEXT_STR8 || sdpdata->dtd == SDP_TEXT_STR16 || sdpdata->dtd == SDP_TEXT_STR32) 1509 if (strlen(sdpdata->val.str) < valuelen) { 1510 strcpy(value, sdpdata->val.str); 1511 return 0; 1512 } 1513 errno = EINVAL; 1514 return -1; 1515} 1516 1517#define get_basic_attr(attrID, pAttrValue, fieldName) \ 1518 sdp_data_t *data = sdp_data_get(rec, attrID); \ 1519 if (data) { \ 1520 *pAttrValue = data->val.fieldName; \ 1521 return 0; \ 1522 } \ 1523 errno = EINVAL; \ 1524 return -1; 1525 1526int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid) 1527{ 1528 get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid); 1529} 1530 1531int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid) 1532{ 1533 get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid); 1534} 1535 1536int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState) 1537{ 1538 get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32); 1539} 1540 1541int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail) 1542{ 1543 get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8); 1544} 1545 1546int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo) 1547{ 1548 get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32); 1549} 1550 1551int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState) 1552{ 1553 get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32); 1554} 1555 1556/* 1557 * NOTE that none of the setXXX() functions below will 1558 * actually update the SDP server, unless the 1559 * {register, update}sdp_record_t() function is invoked. 1560 */ 1561 1562int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *value) 1563{ 1564 sdp_data_t *d = sdp_data_alloc(dtd, value); 1565 if (d) { 1566 sdp_attr_replace(rec, attr, d); 1567 return 0; 1568 } 1569 return -1; 1570} 1571 1572/* 1573 * Set the information attributes of the service 1574 * pointed to by rec. The attributes are 1575 * service name, description and provider name 1576 */ 1577void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc) 1578{ 1579 if (name) 1580 sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY, SDP_TEXT_STR8, (void *)name); 1581 if (prov) 1582 sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY, SDP_TEXT_STR8, (void *)prov); 1583 if (desc) 1584 sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY, SDP_TEXT_STR8, (void *)desc); 1585} 1586 1587static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto) 1588{ 1589 sdp_data_t *seq = NULL; 1590 void *dtds[10], *values[10]; 1591 void **seqDTDs, **seqs; 1592 int i, seqlen; 1593 sdp_list_t *p; 1594 1595 seqlen = sdp_list_len(proto); 1596 seqDTDs = (void **)malloc(seqlen * sizeof(void *)); 1597 seqs = (void **)malloc(seqlen * sizeof(void *)); 1598 for (i = 0, p = proto; p; p = p->next, i++) { 1599 sdp_list_t *elt = (sdp_list_t *)p->data; 1600 sdp_data_t *s; 1601 int pslen = 0; 1602 for (; elt && pslen < sizeof(dtds); elt = elt->next, pslen++) { 1603 sdp_data_t *d = (sdp_data_t *)elt->data; 1604 dtds[pslen] = &d->dtd; 1605 switch (d->dtd) { 1606 case SDP_UUID16: 1607 values[pslen] = &((uuid_t *)d)->value.uuid16; 1608 break; 1609 case SDP_UUID32: 1610 values[pslen] = &((uuid_t *)d)->value.uuid32; 1611 break; 1612 case SDP_UUID128: 1613 values[pslen] = &((uuid_t *)d)->value.uuid128; 1614 break; 1615 case SDP_UINT8: 1616 values[pslen] = &d->val.uint8; 1617 break; 1618 case SDP_UINT16: 1619 values[pslen] = &d->val.uint16; 1620 break; 1621 case SDP_SEQ8: 1622 case SDP_SEQ16: 1623 case SDP_SEQ32: 1624 values[pslen] = d; 1625 break; 1626 // FIXME: more 1627 } 1628 } 1629 s = sdp_seq_alloc(dtds, values, pslen); 1630 if (s) { 1631 seqDTDs[i] = &s->dtd; 1632 seqs[i] = s; 1633 } 1634 } 1635 seq = sdp_seq_alloc(seqDTDs, seqs, seqlen); 1636 free(seqDTDs); 1637 free(seqs); 1638 return seq; 1639} 1640 1641/* 1642 * sets the access protocols of the service specified 1643 * to the value specified in "access_proto" 1644 * 1645 * Note that if there are alternate mechanisms by 1646 * which the service is accessed, then they should 1647 * be specified as sequences 1648 * 1649 * Using a value of NULL for accessProtocols has 1650 * effect of removing this attribute (if previously set) 1651 * 1652 * This function replaces the existing sdp_access_proto_t 1653 * structure (if any) with the new one specified. 1654 * 1655 * returns 0 if successful or -1 if there is a failure. 1656 */ 1657int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *ap) 1658{ 1659 const sdp_list_t *p; 1660 sdp_data_t *protos = 0; 1661 1662 for (p = ap; p; p = p->next) { 1663 sdp_data_t *seq = access_proto_to_dataseq(rec, (sdp_list_t *)p->data); 1664 protos = sdp_seq_append(protos, seq); 1665 } 1666 sdp_attr_add(rec, SDP_ATTR_PROTO_DESC_LIST, protos); 1667 return 0; 1668} 1669 1670/* 1671 * set the "LanguageBase" attributes of the service record 1672 * record to the value specified in "langAttrList". 1673 * 1674 * "langAttrList" is a linked list of "sdp_lang_attr_t" 1675 * objects, one for each language in which user visible 1676 * attributes are present in the service record. 1677 * 1678 * Using a value of NULL for langAttrList has 1679 * effect of removing this attribute (if previously set) 1680 * 1681 * This function replaces the exisiting sdp_lang_attr_t 1682 * structure (if any) with the new one specified. 1683 * 1684 * returns 0 if successful or -1 if there is a failure. 1685 */ 1686int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *seq) 1687{ 1688 uint8_t uint16 = SDP_UINT16; 1689 int status = 0, i = 0, seqlen = sdp_list_len(seq); 1690 void **dtds = (void **)malloc(3 * seqlen * sizeof(void *)); 1691 void **values = (void **)malloc(3 * seqlen * sizeof(void *)); 1692 const sdp_list_t *p; 1693 1694 for (p = seq; p; p = p->next) { 1695 sdp_lang_attr_t *lang = (sdp_lang_attr_t *)p->data; 1696 if (!lang) { 1697 status = -1; 1698 break; 1699 } 1700 dtds[i] = &uint16; 1701 values[i] = &lang->code_ISO639; 1702 i++; 1703 dtds[i] = &uint16; 1704 values[i] = &lang->encoding; 1705 i++; 1706 dtds[i] = &uint16; 1707 values[i] = &lang->base_offset; 1708 i++; 1709 } 1710 if (status == 0) { 1711 sdp_data_t *seq = sdp_seq_alloc(dtds, values, 3 * seqlen); 1712 sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, seq); 1713 } 1714 free(dtds); 1715 free(values); 1716 return status; 1717} 1718 1719/* 1720 * set the "ServiceID" attribute of the service. 1721 * 1722 * This is the UUID of the service. 1723 * 1724 * returns 0 if successful or -1 if there is a failure. 1725 */ 1726void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid) 1727{ 1728 switch (uuid.type) { 1729 case SDP_UUID16: 1730 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID16, &uuid.value.uuid16); 1731 break; 1732 case SDP_UUID32: 1733 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID32, &uuid.value.uuid32); 1734 break; 1735 case SDP_UUID128: 1736 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID128, &uuid.value.uuid128); 1737 break; 1738 } 1739 sdp_pattern_add_uuid(rec, &uuid); 1740} 1741 1742/* 1743 * set the GroupID attribute of the service record defining a group. 1744 * 1745 * This is the UUID of the group. 1746 * 1747 * returns 0 if successful or -1 if there is a failure. 1748 */ 1749void sdp_set_group_id(sdp_record_t *rec, uuid_t uuid) 1750{ 1751 switch (uuid.type) { 1752 case SDP_UUID16: 1753 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID16, &uuid.value.uuid16); 1754 break; 1755 case SDP_UUID32: 1756 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID32, &uuid.value.uuid32); 1757 break; 1758 case SDP_UUID128: 1759 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID128, &uuid.value.uuid128); 1760 break; 1761 } 1762 sdp_pattern_add_uuid(rec, &uuid); 1763} 1764 1765/* 1766 * set the ProfileDescriptorList attribute of the service record 1767 * pointed to by record to the value specified in "profileDesc". 1768 * 1769 * Each element in the list is an object of type 1770 * sdp_profile_desc_t which is a definition of the 1771 * Bluetooth profile that this service conforms to. 1772 * 1773 * Using a value of NULL for profileDesc has 1774 * effect of removing this attribute (if previously set) 1775 * 1776 * This function replaces the exisiting ProfileDescriptorList 1777 * structure (if any) with the new one specified. 1778 * 1779 * returns 0 if successful or -1 if there is a failure. 1780 */ 1781int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles) 1782{ 1783 int status = 0; 1784 uint8_t uuid16 = SDP_UUID16; 1785 uint8_t uuid32 = SDP_UUID32; 1786 uint8_t uuid128 = SDP_UUID128; 1787 uint8_t uint16 = SDP_UINT16; 1788 int i = 0, seqlen = sdp_list_len(profiles); 1789 void **seqDTDs = (void **)malloc(seqlen * sizeof(void *)); 1790 void **seqs = (void **)malloc(seqlen * sizeof(void *)); 1791 const sdp_list_t *p; 1792 1793 for (p = profiles; p; p = p->next) { 1794 sdp_data_t *seq; 1795 void *dtds[2], *values[2]; 1796 sdp_profile_desc_t *profile = (sdp_profile_desc_t *)p->data; 1797 if (!profile) { 1798 status = -1; 1799 break; 1800 } 1801 switch (profile->uuid.type) { 1802 case SDP_UUID16: 1803 dtds[0] = &uuid16; 1804 values[0] = &profile->uuid.value.uuid16; 1805 break; 1806 case SDP_UUID32: 1807 dtds[0] = &uuid32; 1808 values[0] = &profile->uuid.value.uuid32; 1809 break; 1810 case SDP_UUID128: 1811 dtds[0] = &uuid128; 1812 values[0] = &profile->uuid.value.uuid128; 1813 break; 1814 default: 1815 status = -1; 1816 break; 1817 } 1818 dtds[1] = &uint16; 1819 values[1] = &profile->version; 1820 seq = sdp_seq_alloc(dtds, values, 2); 1821 if (seq) { 1822 seqDTDs[i] = &seq->dtd; 1823 seqs[i] = seq; 1824 sdp_pattern_add_uuid(rec, &profile->uuid); 1825 } 1826 i++; 1827 } 1828 if (status == 0) { 1829 sdp_data_t *pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen); 1830 sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq); 1831 } 1832 free(seqDTDs); 1833 free(seqs); 1834 return status; 1835} 1836 1837/* 1838 * sets various URL attributes of the service 1839 * pointed to by record. The URL include 1840 * 1841 * client: a URL to the client's 1842 * platform specific (WinCE, PalmOS) executable 1843 * code that can be used to access this service. 1844 * 1845 * doc: a URL pointing to service documentation 1846 * 1847 * icon: a URL to an icon that can be used to represent 1848 * this service. 1849 * 1850 * Note that you need to pass NULL for any URLs 1851 * that you don't want to set or remove 1852 */ 1853void sdp_set_url_attr(sdp_record_t *rec, const char *client, const char *doc, const char *icon) 1854{ 1855 sdp_attr_add_new(rec, SDP_ATTR_CLNT_EXEC_URL, SDP_URL_STR8, client); 1856 sdp_attr_add_new(rec, SDP_ATTR_DOC_URL, SDP_URL_STR8, doc); 1857 sdp_attr_add_new(rec, SDP_ATTR_ICON_URL, SDP_URL_STR8, icon); 1858} 1859 1860/* 1861 * The code in this function is executed only once per 1862 * thread. We compute the actual bit value of the Bluetooth 1863 * base UUID which is a string defined in bt_std_values.h 1864 * and is assumed to be of the standard form with "-" separators. 1865 * 1866 * The algorithm however converts the string to 4 unsigned longs 1867 * using the strtoul() and assigns the values in sequence to 1868 * the 128bit value 1869 */ 1870uint128_t *sdp_create_base_uuid(void) 1871{ 1872 char baseStr[128]; 1873 int delim = '-'; 1874 unsigned long dataLongValue; 1875 char *delimPtr; 1876 char *dataPtr; 1877 char temp[10]; 1878 int toBeCopied; 1879 char *data; 1880 1881 if (bluetooth_base_uuid == NULL) { 1882 strcpy(baseStr, BASE_UUID); 1883 bluetooth_base_uuid = (uint128_t *)malloc(sizeof(uint128_t)); 1884 data = bluetooth_base_uuid->data; 1885 memset(data, '\0', sizeof(uint128_t)); 1886 memset(temp, '\0', 10); 1887 dataPtr = baseStr; 1888 delimPtr = NULL; 1889 delimPtr = strchr(dataPtr, delim); 1890 toBeCopied = delimPtr - dataPtr; 1891 if (toBeCopied != 8) { 1892 SDPDBG("To be copied(1) : %d\n", toBeCopied); 1893 return NULL; 1894 } 1895 strncpy(temp, dataPtr, toBeCopied); 1896 dataLongValue = htonl(strtoul(temp, NULL, 16)); 1897 memcpy(&data[0], &dataLongValue, 4); 1898 1899 /* 1900 * Get the next 4 bytes (note that there is a "-" 1901 * between them now) 1902 */ 1903 memset(temp, '\0', 10); 1904 dataPtr = delimPtr + 1; 1905 delimPtr = strchr(dataPtr, delim); 1906 toBeCopied = delimPtr - dataPtr; 1907 if (toBeCopied != 4) { 1908 SDPDBG("To be copied(2) : %d\n", toBeCopied); 1909 return NULL; 1910 } 1911 strncpy(temp, dataPtr, toBeCopied); 1912 dataPtr = delimPtr + 1; 1913 delimPtr = strchr(dataPtr, delim); 1914 toBeCopied = delimPtr - dataPtr; 1915 if (toBeCopied != 4) { 1916 SDPDBG("To be copied(3) : %d\n", toBeCopied); 1917 return NULL; 1918 } 1919 strncat(temp, dataPtr, toBeCopied); 1920 dataLongValue = htonl(strtoul(temp, NULL, 16)); 1921 memcpy(&data[4], &dataLongValue, 4); 1922 1923 /* 1924 * Get the last 4 bytes (note that there are 6 bytes 1925 * after the last separator, which is truncated (2+4) 1926 */ 1927 memset(temp, '\0', 10); 1928 dataPtr = delimPtr + 1; 1929 dataPtr = delimPtr + 1; 1930 delimPtr = strchr(dataPtr, delim); 1931 toBeCopied = delimPtr - dataPtr; 1932 if (toBeCopied != 4) { 1933 SDPDBG("To be copied(4) : %d\n", toBeCopied); 1934 return NULL; 1935 } 1936 strncpy(temp, dataPtr, toBeCopied); 1937 strncat(temp, (delimPtr + 1), 4); 1938 dataLongValue = htonl(strtoul(temp, NULL, 16)); 1939 memcpy(&data[8], &dataLongValue, 4); 1940 dataLongValue = htonl(strtoul(delimPtr + 5, NULL, 16)); 1941 memcpy(&data[12], &dataLongValue, 4); 1942 } 1943 return bluetooth_base_uuid; 1944} 1945 1946uuid_t *sdp_uuid16_create(uuid_t *u, uint16_t val) 1947{ 1948 memset(u, 0, sizeof(uuid_t)); 1949 u->type = SDP_UUID16; 1950 u->value.uuid16 = val; 1951 return u; 1952} 1953 1954uuid_t *sdp_uuid32_create(uuid_t *u, uint32_t val) 1955{ 1956 memset(u, 0, sizeof(uuid_t)); 1957 u->type = SDP_UUID32; 1958 u->value.uuid32 = val; 1959 return u; 1960} 1961 1962uuid_t *sdp_uuid128_create(uuid_t *u, const void *val) 1963{ 1964 memset(u, 0, sizeof(uuid_t)); 1965 u->type = SDP_UUID128; 1966 memcpy(&u->value.uuid128, val, sizeof(uint128_t)); 1967 return u; 1968} 1969 1970/* 1971 * UUID comparison function 1972 * returns 0 if uuidValue1 == uuidValue2 else -1 1973 */ 1974int sdp_uuid16_cmp(const void *p1, const void *p2) 1975{ 1976 const uuid_t *u1 = (const uuid_t *)p1; 1977 const uuid_t *u2 = (const uuid_t *)p2; 1978 return memcmp(&u1->value.uuid16, &u2->value.uuid16, sizeof(uint16_t)); 1979} 1980 1981/* 1982 * UUID comparison function 1983 * returns 0 if uuidValue1 == uuidValue2 else -1 1984 */ 1985int sdp_uuid128_cmp(const void *p1, const void *p2) 1986{ 1987 const uuid_t *u1 = (const uuid_t *)p1; 1988 const uuid_t *u2 = (const uuid_t *)p2; 1989 return memcmp(&u1->value.uuid128, &u2->value.uuid128, sizeof(uint128_t)); 1990} 1991 1992/* 1993 * 128 to 16 bit and 32 to 16 bit UUID conversion functions 1994 * yet to be implemented. Note that the input is in NBO in 1995 * both 32 and 128 bit UUIDs and conversion is needed 1996 */ 1997void sdp_uuid16_to_uuid128(uuid_t *uuid128, uuid_t *uuid16) 1998{ 1999 /* 2000 * We have a 16 bit value, which needs to be added to 2001 * bytes 3 and 4 (at indices 2 and 3) of the Bluetooth base 2002 */ 2003 unsigned short data1; 2004 2005 // allocate a 128bit UUID and init to the Bluetooth base UUID 2006 uint128_t *pBTBase128Bit = sdp_create_base_uuid(); 2007 uuid128->value.uuid128 = *pBTBase128Bit; 2008 uuid128->type = SDP_UUID128; 2009 2010 // extract bytes 2 and 3 of 128bit BT base UUID 2011 memcpy(&data1, &pBTBase128Bit->data[2], 2); 2012 2013 // add the given UUID (16 bits) 2014 data1 += htons(uuid16->value.uuid16); 2015 2016 // set bytes 2 and 3 of the 128 bit value 2017 memcpy(&uuid128->value.uuid128.data[2], &data1, 2); 2018} 2019 2020void sdp_uuid32_to_uuid128(uuid_t *uuid128, uuid_t *uuid32) 2021{ 2022 /* 2023 * We have a 32 bit value, which needs to be added to 2024 * bytes 1->4 (at indices 0 thru 3) of the Bluetooth base 2025 */ 2026 unsigned int data0; 2027 2028 // allocate a 128bit UUID and init to the Bluetooth base UUID 2029 uint128_t *pBTBase128Bit = sdp_create_base_uuid(); 2030 uuid128->value.uuid128 = *pBTBase128Bit; 2031 uuid128->type = SDP_UUID128; 2032 2033 // extract first 4 bytes 2034 memcpy(&data0, &pBTBase128Bit->data[0], 4); 2035 2036 // add the given UUID (32bits) 2037 data0 += htonl(uuid32->value.uuid32); 2038 2039 // set the 4 bytes of the 128 bit value 2040 memcpy(&uuid128->value.uuid128.data[0], &data0, 4); 2041} 2042 2043uuid_t *sdp_uuid_to_uuid128(uuid_t *uuid) 2044{ 2045 uuid_t *uuid128 = (uuid_t *)malloc(sizeof(uuid_t)); 2046 memset(uuid128, 0, sizeof(uuid_t)); 2047 switch (uuid->type) { 2048 case SDP_UUID128: 2049 *uuid128 = *uuid; 2050 break; 2051 case SDP_UUID32: 2052 sdp_uuid32_to_uuid128(uuid128, uuid); 2053 break; 2054 case SDP_UUID16: 2055 sdp_uuid16_to_uuid128(uuid128, uuid); 2056 break; 2057 } 2058 return uuid128; 2059} 2060 2061/* 2062 * converts a 128-bit uuid to a 16/32-bit one if possible 2063 * returns true if uuid contains a 16/32-bit UUID at exit 2064 */ 2065int sdp_uuid128_to_uuid(uuid_t *uuid) 2066{ 2067 extern uint128_t *sdp_create_base_uuid(); 2068 int i; 2069 uint128_t *b = sdp_create_base_uuid(); 2070 uint128_t *u = &uuid->value.uuid128; 2071 uint32_t data; 2072 2073 if (uuid->type != SDP_UUID128) 2074 return 1; 2075 2076 for (i = 4; i < sizeof(b->data); i++) 2077 if (b->data[i] != u->data[i]) 2078 return 0; 2079 2080 memcpy(&data, u->data, 4); 2081 data = htonl(data); 2082 if (data <= 0xffff) { 2083 uuid->type = SDP_UUID16; 2084 uuid->value.uuid16 = (uint16_t)data; 2085 } else { 2086 uuid->type = SDP_UUID32; 2087 uuid->value.uuid32 = data; 2088 } 2089 return 1; 2090} 2091 2092/* 2093 * convert a UUID to the 16-bit short-form 2094 */ 2095int sdp_uuid_to_proto(uuid_t *uuid) 2096{ 2097 uuid_t u = *uuid; 2098 if (sdp_uuid128_to_uuid(&u)) { 2099 switch (u.type) { 2100 case SDP_UUID16: 2101 return u.value.uuid16; 2102 case SDP_UUID32: 2103 return u.value.uuid32; 2104 } 2105 } 2106 return 0; 2107} 2108 2109int sdp_uuid_extract(const char *p, uuid_t *uuid, int *scanned) 2110{ 2111 uint8_t type = *(const uint8_t *)p; 2112 2113 if (!SDP_IS_UUID(type)) { 2114 SDPERR("Unknown data type : %d expecting a svc UUID\n", type); 2115 return -1; 2116 } 2117 p += sizeof(uint8_t); 2118 *scanned += sizeof(uint8_t); 2119 if (type == SDP_UUID16) { 2120 sdp_uuid16_create(uuid, ntohs(sdp_get_unaligned((uint16_t *)p))); 2121 *scanned += sizeof(uint16_t); 2122 p += sizeof(uint16_t); 2123 } else if (type == SDP_UUID32) { 2124 sdp_uuid32_create(uuid, ntohl(sdp_get_unaligned((uint32_t *)p))); 2125 *scanned += sizeof(uint32_t); 2126 p += sizeof(uint32_t); 2127 } else { 2128 sdp_uuid128_create(uuid, p); 2129 *scanned += sizeof(uint128_t); 2130 p += sizeof(uint128_t); 2131 } 2132 return 0; 2133} 2134 2135/* 2136 * This function appends data to the PDU buffer "dst" from source "src". 2137 * The data length is also computed and set. 2138 * Should the PDU length exceed 2^8, then sequence type is 2139 * set accordingly and the data is memmove()'d. 2140 */ 2141void sdp_append_to_buf(sdp_buf_t *dst, char *data, int len) 2142{ 2143 char *p = dst->data; 2144 uint8_t dtd = *(uint8_t *)p; 2145 2146 SDPDBG("Append src size: %d\n", len); 2147 SDPDBG("Append dst size: %d\n", dst->data_size); 2148 SDPDBG("Dst buffer size: %d\n", dst->buf_size); 2149 if (dst->data_size + len > dst->buf_size) { 2150 int need = SDP_PDU_CHUNK_SIZE * ((len / SDP_PDU_CHUNK_SIZE) + 1); 2151 dst->data = (char *)realloc(dst->data, dst->buf_size + need); 2152 2153 SDPDBG("Realloc'ing : %d\n", need); 2154 2155 if (dst->data == NULL) { 2156 SDPERR("Realloc fails \n"); 2157 } 2158 dst->buf_size += need; 2159 } 2160 if (dst->data_size == 0 && dtd == 0) { 2161 // create initial sequence 2162 *(uint8_t *)p = SDP_SEQ8; 2163 p += sizeof(uint8_t); 2164 dst->data_size += sizeof(uint8_t); 2165 // reserve space for sequence size 2166 p += sizeof(uint8_t); 2167 dst->data_size += sizeof(uint8_t); 2168 } 2169 2170 memcpy(dst->data + dst->data_size, data, len); 2171 dst->data_size += len; 2172 2173 dtd = *(uint8_t *)dst->data; 2174 if (dst->data_size > UCHAR_MAX && dtd == SDP_SEQ8) { 2175 short offset = sizeof(uint8_t) + sizeof(uint8_t); 2176 memmove(dst->data + offset + 1, dst->data + offset, dst->data_size - offset); 2177 p = dst->data; 2178 *(uint8_t *)p = SDP_SEQ16; 2179 p += sizeof(uint8_t); 2180 dst->data_size += 1; 2181 } 2182 p = dst->data; 2183 dtd = *(uint8_t *)p; 2184 p += sizeof(uint8_t); 2185 switch (dtd) { 2186 case SDP_SEQ8: 2187 *(uint8_t *)p = dst->data_size - sizeof(uint8_t) - sizeof(uint8_t); 2188 break; 2189 case SDP_SEQ16: 2190 sdp_put_unaligned(htons(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t)), (uint16_t *)p); 2191 break; 2192 case SDP_SEQ32: 2193 sdp_put_unaligned(htonl(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t)), (uint32_t *)p); 2194 break; 2195 } 2196} 2197 2198void sdp_append_to_pdu(sdp_buf_t *pdu, sdp_data_t *d) 2199{ 2200 char buf[SDP_SEQ_PDUFORM_SIZE]; 2201 sdp_buf_t append; 2202 2203 append.data = buf; 2204 append.buf_size = sizeof(buf); 2205 append.data_size = 0; 2206 sdp_set_attrid(&append, d->attrId); 2207 sdp_gen_pdu(&append, d); 2208 sdp_append_to_buf(pdu, append.data, append.data_size); 2209} 2210 2211/* 2212 * Registers an sdp record. 2213 * 2214 * It is incorrect to call this method on a record that 2215 * has been already registered with the server. 2216 * 2217 * Returns a non-null value (a pointer) to a service 2218 * record if successful, else -1 setting errno 2219 */ 2220int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags) 2221{ 2222 char *p; 2223 int status = 0; 2224 char *req, *rsp; 2225 int reqsize, rspsize; 2226 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2227 sdp_buf_t pdu; 2228 2229 SDPDBG(""); 2230 2231 if (!session->local) { 2232 errno = EREMOTE; 2233 return -1; 2234 } 2235 req = (char *)malloc(SDP_REQ_BUFFER_SIZE); 2236 rsp = (char *)malloc(SDP_RSP_BUFFER_SIZE); 2237 if (req == NULL || rsp == NULL) { 2238 status = -1; 2239 errno = ENOMEM; 2240 goto end; 2241 } 2242 reqhdr = (sdp_pdu_hdr_t *)req; 2243 reqhdr->pdu_id = SDP_SVC_REGISTER_REQ; 2244 reqhdr->tid = htons(sdp_gen_tid(session)); 2245 reqsize = sizeof(sdp_pdu_hdr_t) + 1; 2246 p = req + sizeof(sdp_pdu_hdr_t); 2247 *p++ = flags; 2248 if (0 > sdp_gen_record_pdu(rec, &pdu)) { 2249 status = -1; 2250 errno = ENOMEM; 2251 goto end; 2252 } 2253 memcpy(p, pdu.data, pdu.data_size); 2254 free(pdu.data); 2255 reqsize += pdu.data_size; 2256 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2257 2258 status = sdp_send_req_w4_rsp(session, req, rsp, reqsize, &rspsize); 2259 if (status < 0) 2260 goto end; 2261 rsphdr = (sdp_pdu_hdr_t *)rsp; 2262 p = rsp + sizeof(sdp_pdu_hdr_t); 2263 if (rsphdr->pdu_id == SDP_SVC_REGISTER_RSP) { 2264 uint32_t handle = ntohl(sdp_get_unaligned((uint32_t *)p)); 2265 sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle); 2266 rec->handle = handle; 2267 sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data); 2268 } 2269end: 2270 if (req) 2271 free(req); 2272 if (rsp) 2273 free(rsp); 2274 return status; 2275} 2276 2277/* 2278 * unregister a service record 2279 */ 2280int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec) 2281{ 2282 char *p; 2283 int status = 0; 2284 char *reqbuf, *rspbuf; 2285 int reqsize = 0, rspsize = 0; 2286 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2287 uint32_t handle = 0; 2288 2289 SDPDBG(""); 2290 2291 handle = rec->handle; 2292 if (handle == SDP_SERVER_RECORD_HANDLE) { 2293 errno = EINVAL; 2294 return -1; 2295 } 2296 if (!session->local) { 2297 errno = EREMOTE; 2298 return -1; 2299 } 2300 reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); 2301 rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); 2302 if (!reqbuf || !rspbuf) { 2303 errno = ENOMEM; 2304 status = -1; 2305 goto end; 2306 } 2307 reqhdr = (sdp_pdu_hdr_t *)reqbuf; 2308 reqhdr->pdu_id = SDP_SVC_REMOVE_REQ; 2309 reqhdr->tid = htons(sdp_gen_tid(session)); 2310 2311 p = reqbuf + sizeof(sdp_pdu_hdr_t); 2312 reqsize = sizeof(sdp_pdu_hdr_t); 2313 sdp_put_unaligned(htonl(handle), (uint32_t *)p); 2314 reqsize += sizeof(uint32_t); 2315 2316 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2317 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2318 if (status == 0) { 2319 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 2320 p = rspbuf + sizeof(sdp_pdu_hdr_t); 2321 status = sdp_get_unaligned((uint16_t *)p); 2322 if (status == 0 && rsphdr->pdu_id == SDP_SVC_REMOVE_RSP) { 2323 SDPDBG("Removing local copy\n"); 2324 sdp_record_free(rec); 2325 } 2326 } 2327end: 2328 if (reqbuf) 2329 free(reqbuf); 2330 if (rspbuf) 2331 free(rspbuf); 2332 return status; 2333} 2334 2335/* 2336 * modify an existing service record 2337 */ 2338int sdp_record_update(sdp_session_t *session, const sdp_record_t *rec) 2339{ 2340 char *p; 2341 int status = 0; 2342 char *reqbuf, *rspbuf; 2343 int reqsize, rspsize; 2344 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2345 uint32_t handle; 2346 sdp_buf_t pdu; 2347 2348 SDPDBG(""); 2349 handle = rec->handle; 2350 2351 if (handle == SDP_SERVER_RECORD_HANDLE) { 2352 errno = EINVAL; 2353 return -1; 2354 } 2355 if (!session->local) { 2356 errno = EREMOTE; 2357 return -1; 2358 } 2359 reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); 2360 rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); 2361 if (!reqbuf || !rspbuf) { 2362 errno = ENOMEM; 2363 status = -1; 2364 goto end; 2365 } 2366 reqhdr = (sdp_pdu_hdr_t *)reqbuf; 2367 reqhdr->pdu_id = SDP_SVC_UPDATE_REQ; 2368 reqhdr->tid = htons(sdp_gen_tid(session)); 2369 2370 p = (char *)(reqbuf + sizeof(sdp_pdu_hdr_t)); 2371 reqsize = sizeof(sdp_pdu_hdr_t); 2372 2373 sdp_put_unaligned(htonl(handle), (uint32_t *)p); 2374 reqsize += sizeof(uint32_t); 2375 p += sizeof(uint32_t); 2376 2377 if (0 > sdp_gen_record_pdu(rec, &pdu)) { 2378 errno = ENOMEM; 2379 status = -1; 2380 goto end; 2381 } 2382 memcpy(p, pdu.data, pdu.data_size); 2383 reqsize += pdu.data_size; 2384 2385 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2386 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2387 2388 SDPDBG("Send req status : %d\n", status); 2389 2390 if (status == 0) { 2391 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 2392 p = rspbuf + sizeof(sdp_pdu_hdr_t); 2393 status = sdp_get_unaligned((uint16_t *)p); 2394 } 2395end: 2396 if (reqbuf) 2397 free(reqbuf); 2398 if (rspbuf) 2399 free(rspbuf); 2400 return status; 2401} 2402 2403sdp_record_t *sdp_record_alloc() 2404{ 2405 sdp_record_t *rec = (sdp_record_t *)malloc(sizeof(sdp_record_t)); 2406 memset((void *)rec, 0, sizeof(sdp_record_t)); 2407 rec->handle = 0xffffffff; 2408 return rec; 2409} 2410 2411/* 2412 * Free the contents of a service record 2413 */ 2414void sdp_record_free(sdp_record_t *rec) 2415{ 2416 sdp_list_free(rec->attrlist, (sdp_free_func_t)sdp_data_free); 2417 sdp_list_free(rec->pattern, free); 2418 free(rec); 2419} 2420 2421void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid) 2422{ 2423 uuid_t *uuid128 = sdp_uuid_to_uuid128(uuid); 2424 2425 SDPDBG("SvcRec : 0x%lx\n", (unsigned long)rec); 2426 SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); 2427 SDPDBG("Trying to add : 0x%lx\n", (unsigned long)uuid128); 2428 2429 if (sdp_list_find(rec->pattern, uuid128, sdp_uuid128_cmp) == NULL) 2430 rec->pattern = sdp_list_insert_sorted(rec->pattern, uuid128, sdp_uuid128_cmp); 2431 else 2432 free(uuid128); 2433 2434 SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); 2435} 2436 2437void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq) 2438{ 2439 for (; seq; seq = seq->next) { 2440 uuid_t *uuid = (uuid_t *)seq->data; 2441 sdp_pattern_add_uuid(rec, uuid); 2442 } 2443} 2444 2445/* 2446 * Extract a sequence of service record handles from a PDU buffer 2447 * and add the entries to a sdp_list_t. Note that the service record 2448 * handles are not in "data element sequence" form, but just like 2449 * an array of service handles 2450 */ 2451static void extract_record_handle_seq(char *pdu, sdp_list_t **seq, int count, int *scanned) 2452{ 2453 sdp_list_t *pSeq = *seq; 2454 char *pdata = pdu; 2455 int n; 2456 2457 for (n = 0; n < count; n++) { 2458 uint32_t *pSvcRec = (uint32_t *) malloc(sizeof(uint32_t)); 2459 *pSvcRec = ntohl(sdp_get_unaligned((uint32_t *)pdata)); 2460 pSeq = sdp_list_append(pSeq, pSvcRec); 2461 pdata += sizeof(uint32_t); 2462 *scanned += sizeof(uint32_t); 2463 } 2464 *seq = pSeq; 2465} 2466/* 2467 * Generate the attribute sequence pdu form 2468 * from sdp_list_t elements. Return length of attr seq 2469 */ 2470static int gen_dataseq_pdu(char *dst, const sdp_list_t *seq, uint8_t dtd) 2471{ 2472 sdp_data_t *dataseq; 2473 void **types, **values; 2474 sdp_buf_t buf; 2475 int i, seqlen = sdp_list_len(seq); 2476 2477 // Fill up the value and the dtd arrays 2478 SDPDBG(""); 2479 2480 memset(&buf, 0, sizeof(sdp_buf_t)); 2481 buf.data = (char *)malloc(SDP_UUID_SEQ_SIZE); 2482 buf.buf_size = SDP_UUID_SEQ_SIZE; 2483 2484 SDPDBG("Seq length : %d\n", seqlen); 2485 2486 types = malloc(seqlen * sizeof(void *)); 2487 values = malloc(seqlen * sizeof(void *)); 2488 for (i = 0; i < seqlen; i++) { 2489 void *data = seq->data; 2490 types[i] = &dtd; 2491 if (SDP_IS_UUID(dtd)) 2492 data = &((uuid_t *)data)->value; 2493 values[i] = data; 2494 seq = seq->next; 2495 } 2496 2497 dataseq = sdp_seq_alloc(types, values, seqlen); 2498 SDPDBG("Data Seq : 0x%p\n", seq); 2499 seqlen = sdp_gen_pdu(&buf, dataseq); 2500 SDPDBG("Copying : %d\n", buf.data_size); 2501 memcpy(dst, buf.data, buf.data_size); 2502 2503 sdp_data_free(dataseq); 2504 2505 free(types); 2506 free(values); 2507 free(buf.data); 2508 return seqlen; 2509} 2510 2511static int gen_searchseq_pdu(char *dst, const sdp_list_t *seq) 2512{ 2513 uuid_t *uuid = (uuid_t *)seq->data; 2514 return gen_dataseq_pdu(dst, seq, uuid->type); 2515} 2516 2517static int gen_attridseq_pdu(char *dst, const sdp_list_t *seq, uint8_t dataType) 2518{ 2519 return gen_dataseq_pdu(dst, seq, dataType); 2520} 2521 2522static int copy_cstate(char *pdata, const sdp_cstate_t *cstate) 2523{ 2524 if (cstate) { 2525 *pdata++ = cstate->length; 2526 memcpy(pdata, cstate->data, cstate->length); 2527 return cstate->length + 1; 2528 } 2529 *pdata = 0; 2530 return 1; 2531} 2532 2533/* 2534 * This is a service search request. 2535 * 2536 * INPUT : 2537 * 2538 * sdp_list_t *search_list 2539 * Singly linked list containing elements of the search 2540 * pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16) 2541 * of the service to be searched 2542 * 2543 * uint16_t max_rec_num 2544 * A 16 bit integer which tells the service, the maximum 2545 * entries that the client can handle in the response. The 2546 * server is obliged not to return > max_rec_num entries 2547 * 2548 * OUTPUT : 2549 * 2550 * int return value 2551 * 0: 2552 * The request completed successfully. This does not 2553 * mean the requested services were found 2554 * -1: 2555 * On any failure and sets errno 2556 * 2557 * sdp_list_t **rsp_list 2558 * This variable is set on a successful return if there are 2559 * non-zero service handles. It is a singly linked list of 2560 * service records (sdp_record_t *) 2561 * 2562 * uint16_t *handleCount 2563 * This is a pointer to a 16 bit integer, which is set to 2564 * indicate the number of service record handles present in 2565 * rec_list 2566 */ 2567int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, 2568 uint16_t max_rec_num, sdp_list_t **rsp) 2569{ 2570 int status = 0; 2571 int reqsize = 0, _reqsize; 2572 int rspsize = 0, rsplen; 2573 int seqlen = 0; 2574 int scanned, total_rec_count, rec_count; 2575 char *pdata, *_pdata; 2576 char *reqbuf, *rspbuf; 2577 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2578 sdp_cstate_t *cstate = NULL; 2579 2580 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 2581 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 2582 if (!reqbuf || !rspbuf) { 2583 errno = ENOMEM; 2584 status = -1; 2585 goto end; 2586 } 2587 reqhdr = (sdp_pdu_hdr_t *)reqbuf; 2588 reqhdr->pdu_id = SDP_SVC_SEARCH_REQ; 2589 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 2590 reqsize = sizeof(sdp_pdu_hdr_t); 2591 2592 // add service class IDs for search 2593 seqlen = gen_searchseq_pdu(pdata, search); 2594 2595 SDPDBG("Data seq added : %d\n", seqlen); 2596 2597 // set the length and increment the pointer 2598 reqsize += seqlen; 2599 pdata += seqlen; 2600 2601 // specify the maximum svc rec count that client expects 2602 sdp_put_unaligned(htons(max_rec_num), (uint16_t *)pdata); 2603 reqsize += sizeof(uint16_t); 2604 pdata += sizeof(uint16_t); 2605 2606 _reqsize = reqsize; 2607 _pdata = pdata; 2608 *rsp = NULL; 2609 2610 do { 2611 // Add continuation state or NULL (first time) 2612 reqsize = _reqsize + copy_cstate(_pdata, cstate); 2613 2614 // Set the request header's param length 2615 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2616 2617 reqhdr->tid = htons(sdp_gen_tid(session)); 2618 /* 2619 * Send the request, wait for response and if 2620 * no error, set the appropriate values and return 2621 */ 2622 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2623 if (status < 0) 2624 goto end; 2625 2626 rsplen = 0; 2627 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 2628 rsplen = ntohs(rsphdr->plen); 2629 2630 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 2631 SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); 2632 status = -1; 2633 goto end; 2634 } 2635 scanned = 0; 2636 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 2637 2638 // net service record match count 2639 total_rec_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); 2640 pdata += sizeof(uint16_t); 2641 scanned += sizeof(uint16_t); 2642 rec_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); 2643 pdata += sizeof(uint16_t); 2644 scanned += sizeof(uint16_t); 2645 2646 SDPDBG("Total svc count: %d\n", total_rec_count); 2647 SDPDBG("Current svc count: %d\n", rec_count); 2648 SDPDBG("ResponseLength: %d\n", rsplen); 2649 2650 if (!rec_count) { 2651 status = -1; 2652 goto end; 2653 } 2654 extract_record_handle_seq(pdata, rsp, rec_count, &scanned); 2655 SDPDBG("BytesScanned : %d\n", scanned); 2656 2657 if (rsplen > scanned) { 2658 uint8_t cstate_len; 2659 2660 pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned; 2661 cstate_len = *(uint8_t *)pdata; 2662 if (cstate_len > 0) { 2663 cstate = (sdp_cstate_t *)pdata; 2664 SDPDBG("Cont state length: %d\n", cstate_len); 2665 } else 2666 cstate = NULL; 2667 } 2668 } while (cstate); 2669 2670 end: 2671 if (reqbuf) 2672 free(reqbuf); 2673 if (rspbuf) 2674 free(rspbuf); 2675 2676 return status; 2677} 2678 2679/* 2680 * This is a service attribute request. 2681 * 2682 * INPUT : 2683 * 2684 * uint32_t handle 2685 * The handle of the service for which the attribute(s) are 2686 * requested 2687 * 2688 * sdp_attrreq_type_t reqtype 2689 * Attribute identifiers are 16 bit unsigned integers specified 2690 * in one of 2 ways described below : 2691 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 2692 * They are the actual attribute identifiers in ascending order 2693 * 2694 * SDP_ATTR_REQ_RANGE - 32bit identifier range 2695 * The high-order 16bits is the start of range 2696 * the low-order 16bits are the end of range 2697 * 0x0000 to 0xFFFF gets all attributes 2698 * 2699 * sdp_list_t *attrid 2700 * Singly linked list containing attribute identifiers desired. 2701 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 2702 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 2703 * 2704 * OUTPUT : 2705 * return sdp_record_t * 2706 * 0: 2707 * On any error and sets errno 2708 * !0: 2709 * The service record 2710 */ 2711sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, 2712 sdp_attrreq_type_t reqtype, const sdp_list_t *attrids) 2713{ 2714 int status = 0; 2715 int reqsize = 0, _reqsize; 2716 int rspsize = 0, rsp_count; 2717 int attr_list_len = 0; 2718 int seqlen = 0; 2719 char *pdata, *_pdata; 2720 char *reqbuf, *rspbuf; 2721 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2722 sdp_cstate_t *cstate = NULL; 2723 uint8_t cstate_len = 0; 2724 sdp_buf_t rsp_concat_buf; 2725 sdp_record_t *rec = 0; 2726 2727 if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) { 2728 errno = EINVAL; 2729 return 0; 2730 } 2731 2732 reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); 2733 rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); 2734 if (!reqbuf || !rspbuf) { 2735 errno = ENOMEM; 2736 status = -1; 2737 goto end; 2738 } 2739 memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t)); 2740 reqhdr = (sdp_pdu_hdr_t *)reqbuf; 2741 reqhdr->pdu_id = SDP_SVC_ATTR_REQ; 2742 2743 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 2744 reqsize = sizeof(sdp_pdu_hdr_t); 2745 2746 // add the service record handle 2747 sdp_put_unaligned(htonl(handle), (uint32_t *)pdata); 2748 reqsize += sizeof(uint32_t); 2749 pdata += sizeof(uint32_t); 2750 2751 // specify the response limit 2752 sdp_put_unaligned(htons(65535), (uint16_t *)pdata); 2753 reqsize += sizeof(uint16_t); 2754 pdata += sizeof(uint16_t); 2755 2756 // get attr seq PDU form 2757 seqlen = gen_attridseq_pdu(pdata, attrids, 2758 reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32); 2759 if (seqlen == -1) { 2760 errno = EINVAL; 2761 status = -1; 2762 goto end; 2763 } 2764 pdata += seqlen; 2765 reqsize += seqlen; 2766 SDPDBG("Attr list length : %d\n", seqlen); 2767 2768 // save before Continuation State 2769 _pdata = pdata; 2770 _reqsize = reqsize; 2771 2772 do { 2773 // add NULL continuation state 2774 reqsize = _reqsize + copy_cstate(_pdata, cstate); 2775 2776 // set the request header's param length 2777 reqhdr->tid = htons(sdp_gen_tid(session)); 2778 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2779 2780 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2781 if (status < 0) 2782 goto end; 2783 rsp_count = 0; 2784 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 2785 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 2786 SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id); 2787 status = -1; 2788 goto end; 2789 } 2790 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 2791 rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); 2792 attr_list_len += rsp_count; 2793 pdata += sizeof(uint16_t); 2794 2795 // if continuation state set need to re-issue request before parsing 2796 cstate_len = *(uint8_t *)(pdata + rsp_count); 2797 2798 SDPDBG("Response id : %d\n", rsphdr->pdu_id); 2799 SDPDBG("Attrlist byte count : %d\n", rsp_count); 2800 SDPDBG("sdp_cstate_t length : %d\n", cstate_len); 2801 2802 /* 2803 * a split response: concatenate intermediate responses 2804 * and the last one (which has cstate_len == 0) 2805 */ 2806 if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { 2807 char *targetPtr = NULL; 2808 2809 cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0; 2810 2811 // build concatenated response buffer 2812 rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); 2813 rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; 2814 targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; 2815 memcpy(targetPtr, pdata, rsp_count); 2816 rsp_concat_buf.data_size += rsp_count; 2817 } 2818 } while (cstate); 2819 2820 if (attr_list_len > 0) { 2821 int scanned = 0; 2822 if (rsp_concat_buf.data_size != 0) 2823 pdata = rsp_concat_buf.data; 2824 rec = sdp_extract_pdu(pdata, &scanned); 2825 2826 if (!rec) 2827 status = -1; 2828 } 2829 2830 end: 2831 if (reqbuf) 2832 free(reqbuf); 2833 if (rsp_concat_buf.data) 2834 free(rsp_concat_buf.data); 2835 if (rspbuf) 2836 free(rspbuf); 2837 return rec; 2838} 2839 2840/* 2841 * This is a service search request combined with the service 2842 * attribute request. First a service class match is done and 2843 * for matching service, requested attributes are extracted 2844 * 2845 * INPUT : 2846 * 2847 * sdp_list_t *search 2848 * Singly linked list containing elements of the search 2849 * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16) 2850 * of the service to be searched 2851 * 2852 * AttributeSpecification attrSpec 2853 * Attribute identifiers are 16 bit unsigned integers specified 2854 * in one of 2 ways described below : 2855 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 2856 * They are the actual attribute identifiers in ascending order 2857 * 2858 * SDP_ATTR_REQ_RANGE - 32bit identifier range 2859 * The high-order 16bits is the start of range 2860 * the low-order 16bits are the end of range 2861 * 0x0000 to 0xFFFF gets all attributes 2862 * 2863 * sdp_list_t *attrids 2864 * Singly linked list containing attribute identifiers desired. 2865 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 2866 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 2867 * 2868 * OUTPUT : 2869 * int return value 2870 * 0: 2871 * The request completed successfully. This does not 2872 * mean the requested services were found 2873 * -1: 2874 * On any error and sets errno 2875 * 2876 * sdp_list_t **rsp 2877 * This variable is set on a successful return to point to 2878 * service(s) found. Each element of this list is of type 2879 * sdp_record_t* (of the services which matched the search list) 2880 */ 2881int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrids, sdp_list_t **rsp) 2882{ 2883 int status = 0; 2884 int reqsize = 0, _reqsize; 2885 int rspsize = 0; 2886 int seqlen = 0, attr_list_len = 0; 2887 int rsp_count = 0, cstate_len = 0; 2888 char *pdata, *_pdata; 2889 char *reqbuf, *rspbuf; 2890 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2891 uint8_t dataType; 2892 sdp_list_t *rec_list = NULL; 2893 sdp_buf_t rsp_concat_buf; 2894 sdp_cstate_t *cstate = NULL; 2895 2896 if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) { 2897 errno = EINVAL; 2898 return -1; 2899 } 2900 reqbuf = (char *)malloc(SDP_REQ_BUFFER_SIZE); 2901 rspbuf = (char *)malloc(SDP_RSP_BUFFER_SIZE); 2902 if (!reqbuf || !rspbuf) { 2903 errno = ENOMEM; 2904 status = -1; 2905 goto end; 2906 } 2907 2908 memset((char *)&rsp_concat_buf, 0, sizeof(sdp_buf_t)); 2909 reqhdr = (sdp_pdu_hdr_t *)reqbuf; 2910 reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ; 2911 2912 // generate PDU 2913 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 2914 reqsize = sizeof(sdp_pdu_hdr_t); 2915 2916 // add service class IDs for search 2917 seqlen = gen_searchseq_pdu(pdata, search); 2918 2919 SDPDBG("Data seq added : %d\n", seqlen); 2920 2921 // now set the length and increment the pointer 2922 reqsize += seqlen; 2923 pdata += seqlen; 2924 2925 sdp_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *)pdata); 2926 reqsize += sizeof(uint16_t); 2927 pdata += sizeof(uint16_t); 2928 2929 SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); 2930 2931 // get attr seq PDU form 2932 seqlen = gen_attridseq_pdu(pdata, attrids, 2933 reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16: SDP_UINT32); 2934 if (seqlen == -1) { 2935 status = EINVAL; 2936 goto end; 2937 } 2938 pdata += seqlen; 2939 SDPDBG("Attr list length : %d\n", seqlen); 2940 reqsize += seqlen; 2941 *rsp = 0; 2942 2943 // save before Continuation State 2944 _pdata = pdata; 2945 _reqsize = reqsize; 2946 2947 do { 2948 reqhdr->tid = htons(sdp_gen_tid(session)); 2949 2950 // add continuation state (can be null) 2951 reqsize = _reqsize + copy_cstate(_pdata, cstate); 2952 2953 // set the request header's param length 2954 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2955 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 2956 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2957 if (status < 0) { 2958 SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); 2959 goto end; 2960 } 2961 2962 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 2963 status = -1; 2964 goto end; 2965 } 2966 2967 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 2968 rsp_count = ntohs(sdp_get_unaligned((uint16_t *)pdata)); 2969 attr_list_len += rsp_count; 2970 pdata += sizeof(uint16_t); // pdata points to attribute list 2971 cstate_len = *(uint8_t *)(pdata + rsp_count); 2972 2973 SDPDBG("Attrlist byte count : %d\n", attr_list_len); 2974 SDPDBG("Response byte count : %d\n", rsp_count); 2975 SDPDBG("Cstate length : %d\n", cstate_len); 2976 /* 2977 * This is a split response, need to concatenate intermediate 2978 * responses and the last one which will have cstate_len == 0 2979 */ 2980 if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { 2981 char *targetPtr = NULL; 2982 2983 cstate = cstate_len > 0? (sdp_cstate_t *)(pdata + rsp_count): 0; 2984 2985 // build concatenated response buffer 2986 rsp_concat_buf.data = (char *)realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); 2987 targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; 2988 rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; 2989 memcpy(targetPtr, pdata, rsp_count); 2990 rsp_concat_buf.data_size += rsp_count; 2991 } 2992 } while (cstate); 2993 2994 if (attr_list_len > 0) { 2995 int scanned = 0; 2996 2997 if (rsp_concat_buf.data_size != 0) 2998 pdata = rsp_concat_buf.data; 2999 3000 /* 3001 * Response is a sequence of sequence(s) for one or 3002 * more data element sequence(s) representing services 3003 * for which attributes are returned 3004 */ 3005 scanned = sdp_extract_seqtype(pdata, &dataType, &seqlen); 3006 3007 SDPDBG("Bytes scanned : %d\n", scanned); 3008 SDPDBG("Seq length : %d\n", seqlen); 3009 3010 if (scanned && seqlen) { 3011 pdata += scanned; 3012 do { 3013 int recsize = 0; 3014 sdp_record_t *rec = sdp_extract_pdu(pdata, &recsize); 3015 if (rec == NULL) { 3016 SDPERR("SVC REC is null\n"); 3017 status = -1; 3018 goto end; 3019 } 3020 scanned += recsize; 3021 pdata += recsize; 3022 3023 SDPDBG("Loc seq length : %d\n", recsize); 3024 SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle); 3025 SDPDBG("Bytes scanned : %d\n", scanned); 3026 SDPDBG("Attrlist byte count : %d\n", attr_list_len); 3027 rec_list = sdp_list_append(rec_list, rec); 3028 } while (scanned < attr_list_len); 3029 3030 SDPDBG("Successful scan of service attr lists\n"); 3031 *rsp = rec_list; 3032 } 3033 } 3034 end: 3035 if (rsp_concat_buf.data) 3036 free(rsp_concat_buf.data); 3037 if (reqbuf) 3038 free(reqbuf); 3039 if (rspbuf) 3040 free(rspbuf); 3041 return status; 3042} 3043 3044/* 3045 * Find devices in the piconet. 3046 */ 3047int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *found) 3048{ 3049 int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0); 3050 if (n < 0) { 3051 SDPERR("Inquiry failed:%s", strerror(errno)); 3052 return -1; 3053 } 3054 *found = n; 3055 return 0; 3056} 3057 3058int sdp_close(sdp_session_t *session) 3059{ 3060 int ret = close(session->sock); 3061 free(session); 3062 return ret; 3063} 3064 3065static inline int sdp_is_local(const bdaddr_t *device) 3066{ 3067 return memcmp(device, BDADDR_LOCAL, sizeof(bdaddr_t)) == 0; 3068} 3069 3070sdp_session_t *sdp_connect(const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags) 3071{ 3072 sdp_session_t *session = malloc(sizeof(sdp_session_t)); 3073 if (!session) 3074 return session; 3075 memset(session, 0, sizeof(*session)); 3076 session->flags = flags; 3077 if (sdp_is_local(dst)) { 3078 struct sockaddr_un sa; 3079 3080 // create local unix connection 3081 session->sock = socket(PF_UNIX, SOCK_STREAM, 0); 3082 session->local = 1; 3083 if (session->sock >= 0) { 3084 sa.sun_family = AF_UNIX; 3085 strcpy(sa.sun_path, SDP_UNIX_PATH); 3086 if (connect(session->sock, (struct sockaddr *)&sa, sizeof(sa)) == 0) 3087 return session; 3088 } 3089 } else { 3090 struct sockaddr_l2 sa; 3091 3092 // create L2CAP connection 3093 session->sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 3094 session->local = 0; 3095 if (session->sock >= 0) { 3096 sa.l2_family = AF_BLUETOOTH; 3097 sa.l2_psm = 0; 3098 if (bacmp(src, BDADDR_ANY) != 0) { 3099 sa.l2_bdaddr = *src; 3100 if (0 > bind(session->sock, (struct sockaddr *)&sa, sizeof(sa))) 3101 goto fail; 3102 } 3103 sa.l2_psm = htobs(SDP_PSM); 3104 sa.l2_bdaddr = *dst; 3105 do 3106 if (connect(session->sock, (struct sockaddr *)&sa, sizeof(sa)) == 0) 3107 return session; 3108 while (errno == EBUSY && (flags & SDP_RETRY_IF_BUSY)); 3109 } 3110 } 3111fail: 3112 if (session->sock >= 0) 3113 close(session->sock); 3114 free(session); 3115 return 0; 3116} 3117