sdp.c revision 8232558057813074ce6bdb3317a9fb4888f7b8e3
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-2009 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 as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30 31#include <stdio.h> 32#include <errno.h> 33#include <fcntl.h> 34#include <unistd.h> 35#include <stdlib.h> 36#include <limits.h> 37#include <string.h> 38#include <syslog.h> 39#include <sys/time.h> 40#include <sys/types.h> 41#include <sys/socket.h> 42#include <sys/un.h> 43#include <netinet/in.h> 44 45#include "bluetooth.h" 46#include "hci.h" 47#include "hci_lib.h" 48#include "l2cap.h" 49#include "sdp.h" 50#include "sdp_lib.h" 51 52#define SDPINF(fmt, arg...) syslog(LOG_INFO, fmt "\n", ## arg) 53#define SDPERR(fmt, arg...) syslog(LOG_ERR, "%s: " fmt "\n", __func__ , ## arg) 54 55#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 56 57#ifdef SDP_DEBUG 58#define SDPDBG(fmt, arg...) syslog(LOG_DEBUG, "%s: " fmt "\n", __func__ , ## arg) 59#else 60#define SDPDBG(fmt...) 61#endif 62 63#if __BYTE_ORDER == __BIG_ENDIAN 64#define ntoh64(x) (x) 65static inline void ntoh128(uint128_t *src, uint128_t *dst) 66{ 67 int i; 68 for (i = 0; i < 16; i++) 69 dst->data[i] = src->data[i]; 70} 71#else 72static inline uint64_t ntoh64(uint64_t n) 73{ 74 uint64_t h; 75 uint64_t tmp = ntohl(n & 0x00000000ffffffff); 76 h = ntohl(n >> 32); 77 h |= tmp << 32; 78 return h; 79} 80static inline void ntoh128(uint128_t *src, uint128_t *dst) 81{ 82 int i; 83 for (i = 0; i < 16; i++) 84 dst->data[15 - i] = src->data[i]; 85} 86#endif 87 88#define hton64(x) ntoh64(x) 89#define hton128(x, y) ntoh128(x, y) 90 91#define BASE_UUID "00000000-0000-1000-8000-00805F9B34FB" 92 93static uint128_t bluetooth_base_uuid = { 94 .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 95 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB } 96}; 97 98#define SDP_MAX_ATTR_LEN 65535 99 100static sdp_data_t *sdp_copy_seq(sdp_data_t *data); 101static int sdp_attr_add_new_with_length(sdp_record_t *rec, 102 uint16_t attr, uint8_t dtd, const void *value, uint32_t len); 103static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d); 104 105/* Message structure. */ 106struct tupla { 107 int index; 108 char *str; 109}; 110 111static struct tupla Protocol[] = { 112 { SDP_UUID, "SDP" }, 113 { UDP_UUID, "UDP" }, 114 { RFCOMM_UUID, "RFCOMM" }, 115 { TCP_UUID, "TCP" }, 116 { TCS_BIN_UUID, "TCS-BIN" }, 117 { TCS_AT_UUID, "TCS-AT" }, 118 { OBEX_UUID, "OBEX" }, 119 { IP_UUID, "IP" }, 120 { FTP_UUID, "FTP" }, 121 { HTTP_UUID, "HTTP" }, 122 { WSP_UUID, "WSP" }, 123 { BNEP_UUID, "BNEP" }, 124 { UPNP_UUID, "UPNP" }, 125 { HIDP_UUID, "HIDP" }, 126 { HCRP_CTRL_UUID, "HCRP-Ctrl" }, 127 { HCRP_DATA_UUID, "HCRP-Data" }, 128 { HCRP_NOTE_UUID, "HCRP-Notify" }, 129 { AVCTP_UUID, "AVCTP" }, 130 { AVDTP_UUID, "AVDTP" }, 131 { CMTP_UUID, "CMTP" }, 132 { UDI_UUID, "UDI" }, 133 { MCAP_CTRL_UUID, "MCAP-Ctrl" }, 134 { MCAP_DATA_UUID, "MCAP-Data" }, 135 { L2CAP_UUID, "L2CAP" }, 136 { 0 } 137}; 138 139static struct tupla ServiceClass[] = { 140 { SDP_SERVER_SVCLASS_ID, "SDP Server" }, 141 { BROWSE_GRP_DESC_SVCLASS_ID, "Browse Group Descriptor" }, 142 { PUBLIC_BROWSE_GROUP, "Public Browse Group" }, 143 { SERIAL_PORT_SVCLASS_ID, "Serial Port" }, 144 { LAN_ACCESS_SVCLASS_ID, "LAN Access Using PPP" }, 145 { DIALUP_NET_SVCLASS_ID, "Dialup Networking" }, 146 { IRMC_SYNC_SVCLASS_ID, "IrMC Sync" }, 147 { OBEX_OBJPUSH_SVCLASS_ID, "OBEX Object Push" }, 148 { OBEX_FILETRANS_SVCLASS_ID, "OBEX File Transfer" }, 149 { IRMC_SYNC_CMD_SVCLASS_ID, "IrMC Sync Command" }, 150 { HEADSET_SVCLASS_ID, "Headset" }, 151 { CORDLESS_TELEPHONY_SVCLASS_ID, "Cordless Telephony" }, 152 { AUDIO_SOURCE_SVCLASS_ID, "Audio Source" }, 153 { AUDIO_SINK_SVCLASS_ID, "Audio Sink" }, 154 { AV_REMOTE_TARGET_SVCLASS_ID, "AV Remote Target" }, 155 { ADVANCED_AUDIO_SVCLASS_ID, "Advanced Audio" }, 156 { AV_REMOTE_SVCLASS_ID, "AV Remote" }, 157 { VIDEO_CONF_SVCLASS_ID, "Video Conferencing" }, 158 { INTERCOM_SVCLASS_ID, "Intercom" }, 159 { FAX_SVCLASS_ID, "Fax" }, 160 { HEADSET_AGW_SVCLASS_ID, "Headset Audio Gateway" }, 161 { WAP_SVCLASS_ID, "WAP" }, 162 { WAP_CLIENT_SVCLASS_ID, "WAP Client" }, 163 { PANU_SVCLASS_ID, "PAN User" }, 164 { NAP_SVCLASS_ID, "Network Access Point" }, 165 { GN_SVCLASS_ID, "PAN Group Network" }, 166 { DIRECT_PRINTING_SVCLASS_ID, "Direct Printing" }, 167 { REFERENCE_PRINTING_SVCLASS_ID, "Reference Printing" }, 168 { IMAGING_SVCLASS_ID, "Imaging" }, 169 { IMAGING_RESPONDER_SVCLASS_ID, "Imaging Responder" }, 170 { IMAGING_ARCHIVE_SVCLASS_ID, "Imaging Automatic Archive" }, 171 { IMAGING_REFOBJS_SVCLASS_ID, "Imaging Referenced Objects" }, 172 { HANDSFREE_SVCLASS_ID, "Handsfree" }, 173 { HANDSFREE_AGW_SVCLASS_ID, "Handsfree Audio Gateway" }, 174 { DIRECT_PRT_REFOBJS_SVCLASS_ID, "Direct Printing Ref. Objects" }, 175 { REFLECTED_UI_SVCLASS_ID, "Reflected UI" }, 176 { BASIC_PRINTING_SVCLASS_ID, "Basic Printing" }, 177 { PRINTING_STATUS_SVCLASS_ID, "Printing Status" }, 178 { HID_SVCLASS_ID, "Human Interface Device" }, 179 { HCR_SVCLASS_ID, "Hardcopy Cable Replacement" }, 180 { HCR_PRINT_SVCLASS_ID, "HCR Print" }, 181 { HCR_SCAN_SVCLASS_ID, "HCR Scan" }, 182 { CIP_SVCLASS_ID, "Common ISDN Access" }, 183 { VIDEO_CONF_GW_SVCLASS_ID, "Video Conferencing Gateway" }, 184 { UDI_MT_SVCLASS_ID, "UDI MT" }, 185 { UDI_TA_SVCLASS_ID, "UDI TA" }, 186 { AV_SVCLASS_ID, "Audio/Video" }, 187 { SAP_SVCLASS_ID, "SIM Access" }, 188 { PBAP_PCE_SVCLASS_ID, "Phonebook Access - PCE" }, 189 { PBAP_PSE_SVCLASS_ID, "Phonebook Access - PSE" }, 190 { PBAP_SVCLASS_ID, "Phonebook Access" }, 191 { PNP_INFO_SVCLASS_ID, "PnP Information" }, 192 { GENERIC_NETWORKING_SVCLASS_ID, "Generic Networking" }, 193 { GENERIC_FILETRANS_SVCLASS_ID, "Generic File Transfer" }, 194 { GENERIC_AUDIO_SVCLASS_ID, "Generic Audio" }, 195 { GENERIC_TELEPHONY_SVCLASS_ID, "Generic Telephony" }, 196 { UPNP_SVCLASS_ID, "UPnP" }, 197 { UPNP_IP_SVCLASS_ID, "UPnP IP" }, 198 { UPNP_PAN_SVCLASS_ID, "UPnP PAN" }, 199 { UPNP_LAP_SVCLASS_ID, "UPnP LAP" }, 200 { UPNP_L2CAP_SVCLASS_ID, "UPnP L2CAP" }, 201 { VIDEO_SOURCE_SVCLASS_ID, "Video Source" }, 202 { VIDEO_SINK_SVCLASS_ID, "Video Sink" }, 203 { VIDEO_DISTRIBUTION_SVCLASS_ID, "Video Distribution" }, 204 { MDP_SVCLASS_ID, "MDP" }, 205 { MDP_SOURCE_SVCLASS_ID, "MDP Source" }, 206 { MDP_SINK_SVCLASS_ID, "MDP Sink" }, 207 { APPLE_AGENT_SVCLASS_ID, "Apple Agent" }, 208 { 0 } 209}; 210 211#define Profile ServiceClass 212 213static char *string_lookup(struct tupla *pt0, int index) 214{ 215 struct tupla *pt; 216 217 for (pt = pt0; pt->index; pt++) 218 if (pt->index == index) 219 return pt->str; 220 221 return ""; 222} 223 224static char *string_lookup_uuid(struct tupla *pt0, const uuid_t* uuid) 225{ 226 uuid_t tmp_uuid; 227 228 memcpy(&tmp_uuid, uuid, sizeof(tmp_uuid)); 229 230 if (sdp_uuid128_to_uuid(&tmp_uuid)) { 231 switch (tmp_uuid.type) { 232 case SDP_UUID16: 233 return string_lookup(pt0, tmp_uuid.value.uuid16); 234 case SDP_UUID32: 235 return string_lookup(pt0, tmp_uuid.value.uuid32); 236 } 237 } 238 239 return ""; 240} 241 242/* 243 * Prints into a string the Protocol UUID 244 * coping a maximum of n characters. 245 */ 246static int uuid2str(struct tupla *message, const uuid_t *uuid, char *str, size_t n) 247{ 248 char *str2; 249 250 if (!uuid) { 251 snprintf(str, n, "NULL"); 252 return -2; 253 } 254 255 switch (uuid->type) { 256 case SDP_UUID16: 257 str2 = string_lookup(message, uuid->value.uuid16); 258 snprintf(str, n, "%s", str2); 259 break; 260 case SDP_UUID32: 261 str2 = string_lookup(message, uuid->value.uuid32); 262 snprintf(str, n, "%s", str2); 263 break; 264 case SDP_UUID128: 265 str2 = string_lookup_uuid(message, uuid); 266 snprintf(str, n, "%s", str2); 267 break; 268 default: 269 snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type); 270 return -1; 271 } 272 273 return 0; 274} 275 276int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n) 277{ 278 return uuid2str(Protocol, uuid, str, n); 279} 280 281int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n) 282{ 283 return uuid2str(ServiceClass, uuid, str, n); 284} 285 286int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n) 287{ 288 return uuid2str(Profile, uuid, str, n); 289} 290 291/* 292 * convert the UUID to string, copying a maximum of n characters. 293 */ 294int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n) 295{ 296 if (!uuid) { 297 snprintf(str, n, "NULL"); 298 return -2; 299 } 300 switch (uuid->type) { 301 case SDP_UUID16: 302 snprintf(str, n, "%.4x", uuid->value.uuid16); 303 break; 304 case SDP_UUID32: 305 snprintf(str, n, "%.8x", uuid->value.uuid32); 306 break; 307 case SDP_UUID128:{ 308 unsigned int data0; 309 unsigned short data1; 310 unsigned short data2; 311 unsigned short data3; 312 unsigned int data4; 313 unsigned short data5; 314 315 memcpy(&data0, &uuid->value.uuid128.data[0], 4); 316 memcpy(&data1, &uuid->value.uuid128.data[4], 2); 317 memcpy(&data2, &uuid->value.uuid128.data[6], 2); 318 memcpy(&data3, &uuid->value.uuid128.data[8], 2); 319 memcpy(&data4, &uuid->value.uuid128.data[10], 4); 320 memcpy(&data5, &uuid->value.uuid128.data[14], 2); 321 322 snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x", 323 ntohl(data0), ntohs(data1), 324 ntohs(data2), ntohs(data3), 325 ntohl(data4), ntohs(data5)); 326 } 327 break; 328 default: 329 snprintf(str, n, "Type of UUID (%x) unknown.", uuid->type); 330 return -1; /* Enum type of UUID not set */ 331 } 332 return 0; 333} 334 335#ifdef SDP_DEBUG 336/* 337 * Function prints the UUID in hex as per defined syntax - 338 * 339 * 4bytes-2bytes-2bytes-2bytes-6bytes 340 * 341 * There is some ugly code, including hardcoding, but 342 * that is just the way it is converting 16 and 32 bit 343 * UUIDs to 128 bit as defined in the SDP doc 344 */ 345void sdp_uuid_print(const uuid_t *uuid) 346{ 347 if (uuid == NULL) { 348 SDPERR("Null passed to print UUID\n"); 349 return; 350 } 351 if (uuid->type == SDP_UUID16) { 352 SDPDBG(" uint16_t : 0x%.4x\n", uuid->value.uuid16); 353 } else if (uuid->type == SDP_UUID32) { 354 SDPDBG(" uint32_t : 0x%.8x\n", uuid->value.uuid32); 355 } else if (uuid->type == SDP_UUID128) { 356 unsigned int data0; 357 unsigned short data1; 358 unsigned short data2; 359 unsigned short data3; 360 unsigned int data4; 361 unsigned short data5; 362 363 memcpy(&data0, &uuid->value.uuid128.data[0], 4); 364 memcpy(&data1, &uuid->value.uuid128.data[4], 2); 365 memcpy(&data2, &uuid->value.uuid128.data[6], 2); 366 memcpy(&data3, &uuid->value.uuid128.data[8], 2); 367 memcpy(&data4, &uuid->value.uuid128.data[10], 4); 368 memcpy(&data5, &uuid->value.uuid128.data[14], 2); 369 370 SDPDBG(" uint128_t : 0x%.8x-", ntohl(data0)); 371 SDPDBG("%.4x-", ntohs(data1)); 372 SDPDBG("%.4x-", ntohs(data2)); 373 SDPDBG("%.4x-", ntohs(data3)); 374 SDPDBG("%.8x", ntohl(data4)); 375 SDPDBG("%.4x\n", ntohs(data5)); 376 } else 377 SDPERR("Enum type of UUID not set\n"); 378} 379#endif 380 381sdp_data_t *sdp_data_alloc_with_length(uint8_t dtd, const void *value, 382 uint32_t length) 383{ 384 sdp_data_t *seq; 385 sdp_data_t *d = malloc(sizeof(sdp_data_t)); 386 387 if (!d) 388 return NULL; 389 390 memset(d, 0, sizeof(sdp_data_t)); 391 d->dtd = dtd; 392 d->unitSize = sizeof(uint8_t); 393 394 switch (dtd) { 395 case SDP_DATA_NIL: 396 break; 397 case SDP_UINT8: 398 d->val.uint8 = *(uint8_t *) value; 399 d->unitSize += sizeof(uint8_t); 400 break; 401 case SDP_INT8: 402 case SDP_BOOL: 403 d->val.int8 = *(int8_t *) value; 404 d->unitSize += sizeof(int8_t); 405 break; 406 case SDP_UINT16: 407 d->val.uint16 = bt_get_unaligned((uint16_t *) value); 408 d->unitSize += sizeof(uint16_t); 409 break; 410 case SDP_INT16: 411 d->val.int16 = bt_get_unaligned((int16_t *) value); 412 d->unitSize += sizeof(int16_t); 413 break; 414 case SDP_UINT32: 415 d->val.uint32 = bt_get_unaligned((uint32_t *) value); 416 d->unitSize += sizeof(uint32_t); 417 break; 418 case SDP_INT32: 419 d->val.int32 = bt_get_unaligned((int32_t *) value); 420 d->unitSize += sizeof(int32_t); 421 break; 422 case SDP_INT64: 423 d->val.int64 = bt_get_unaligned((int64_t *) value); 424 d->unitSize += sizeof(int64_t); 425 break; 426 case SDP_UINT64: 427 d->val.uint64 = bt_get_unaligned((uint64_t *) value); 428 d->unitSize += sizeof(uint64_t); 429 break; 430 case SDP_UINT128: 431 memcpy(&d->val.uint128.data, value, sizeof(uint128_t)); 432 d->unitSize += sizeof(uint128_t); 433 break; 434 case SDP_INT128: 435 memcpy(&d->val.int128.data, value, sizeof(uint128_t)); 436 d->unitSize += sizeof(uint128_t); 437 break; 438 case SDP_UUID16: 439 sdp_uuid16_create(&d->val.uuid, bt_get_unaligned((uint16_t *) value)); 440 d->unitSize += sizeof(uint16_t); 441 break; 442 case SDP_UUID32: 443 sdp_uuid32_create(&d->val.uuid, bt_get_unaligned((uint32_t *) value)); 444 d->unitSize += sizeof(uint32_t); 445 break; 446 case SDP_UUID128: 447 sdp_uuid128_create(&d->val.uuid, value); 448 d->unitSize += sizeof(uint128_t); 449 break; 450 case SDP_URL_STR8: 451 case SDP_URL_STR16: 452 case SDP_TEXT_STR8: 453 case SDP_TEXT_STR16: 454 if (!value) { 455 free(d); 456 return NULL; 457 } 458 459 d->unitSize += length; 460 if (length <= USHRT_MAX) { 461 d->val.str = malloc(length); 462 if (!d->val.str) { 463 free(d); 464 return NULL; 465 } 466 467 memcpy(d->val.str, value, length); 468 } else { 469 SDPERR("Strings of size > USHRT_MAX not supported\n"); 470 free(d); 471 d = NULL; 472 } 473 break; 474 case SDP_URL_STR32: 475 case SDP_TEXT_STR32: 476 SDPERR("Strings of size > USHRT_MAX not supported\n"); 477 break; 478 case SDP_ALT8: 479 case SDP_ALT16: 480 case SDP_ALT32: 481 case SDP_SEQ8: 482 case SDP_SEQ16: 483 case SDP_SEQ32: 484 if (dtd == SDP_ALT8 || dtd == SDP_SEQ8) 485 d->unitSize += sizeof(uint8_t); 486 else if (dtd == SDP_ALT16 || dtd == SDP_SEQ16) 487 d->unitSize += sizeof(uint16_t); 488 else if (dtd == SDP_ALT32 || dtd == SDP_SEQ32) 489 d->unitSize += sizeof(uint32_t); 490 seq = (sdp_data_t *)value; 491 d->val.dataseq = seq; 492 for (; seq; seq = seq->next) 493 d->unitSize += seq->unitSize; 494 break; 495 default: 496 free(d); 497 d = NULL; 498 } 499 500 return d; 501} 502 503sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value) 504{ 505 uint32_t length; 506 507 switch (dtd) { 508 case SDP_URL_STR8: 509 case SDP_URL_STR16: 510 case SDP_TEXT_STR8: 511 case SDP_TEXT_STR16: 512 if (!value) 513 return NULL; 514 515 length = strlen((char *) value); 516 break; 517 default: 518 length = 0; 519 break; 520 } 521 522 return sdp_data_alloc_with_length(dtd, value, length); 523} 524 525sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *d) 526{ 527 if (seq) { 528 sdp_data_t *p; 529 for (p = seq; p->next; p = p->next); 530 p->next = d; 531 } else 532 seq = d; 533 d->next = NULL; 534 return seq; 535} 536 537sdp_data_t *sdp_seq_alloc_with_length(void **dtds, void **values, int *length, 538 int len) 539{ 540 sdp_data_t *curr = NULL, *seq = NULL; 541 int i; 542 543 for (i = 0; i < len; i++) { 544 sdp_data_t *data; 545 int8_t dtd = *(uint8_t *) dtds[i]; 546 547 if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32) 548 data = (sdp_data_t *) values[i]; 549 else 550 data = sdp_data_alloc_with_length(dtd, values[i], length[i]); 551 552 if (!data) 553 return NULL; 554 555 if (curr) 556 curr->next = data; 557 else 558 seq = data; 559 560 curr = data; 561 } 562 563 return sdp_data_alloc_with_length(SDP_SEQ8, seq, length[i]); 564} 565 566sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len) 567{ 568 sdp_data_t *curr = NULL, *seq = NULL; 569 int i; 570 571 for (i = 0; i < len; i++) { 572 sdp_data_t *data; 573 uint8_t dtd = *(uint8_t *) dtds[i]; 574 575 if (dtd >= SDP_SEQ8 && dtd <= SDP_ALT32) 576 data = (sdp_data_t *) values[i]; 577 else 578 data = sdp_data_alloc(dtd, values[i]); 579 580 if (!data) 581 return NULL; 582 583 if (curr) 584 curr->next = data; 585 else 586 seq = data; 587 588 curr = data; 589 } 590 591 return sdp_data_alloc(SDP_SEQ8, seq); 592} 593 594static void extract_svclass_uuid(sdp_data_t *data, uuid_t *uuid) 595{ 596 sdp_data_t *d; 597 598 if (!data || data->dtd < SDP_SEQ8 || data->dtd > SDP_SEQ32) 599 return; 600 601 d = data->val.dataseq; 602 if (!d) 603 return; 604 605 if (d->dtd < SDP_UUID16 || d->dtd > SDP_UUID128) 606 return; 607 608 *uuid = d->val.uuid; 609} 610 611int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *d) 612{ 613 sdp_data_t *p = sdp_data_get(rec, attr); 614 615 if (p) 616 return -1; 617 618 d->attrId = attr; 619 rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func); 620 621 if (attr == SDP_ATTR_SVCLASS_ID_LIST) 622 extract_svclass_uuid(d, &rec->svclass); 623 624 return 0; 625} 626 627void sdp_attr_remove(sdp_record_t *rec, uint16_t attr) 628{ 629 sdp_data_t *d = sdp_data_get(rec, attr); 630 631 if (d) 632 rec->attrlist = sdp_list_remove(rec->attrlist, d); 633 634 if (attr == SDP_ATTR_SVCLASS_ID_LIST) 635 memset(&rec->svclass, 0, sizeof(rec->svclass)); 636} 637 638void sdp_set_seq_len(uint8_t *ptr, uint32_t length) 639{ 640 uint8_t dtd = *(uint8_t *) ptr++; 641 642 switch (dtd) { 643 case SDP_SEQ8: 644 case SDP_ALT8: 645 case SDP_TEXT_STR8: 646 case SDP_URL_STR8: 647 *(uint8_t *)ptr = (uint8_t) length; 648 break; 649 case SDP_SEQ16: 650 case SDP_ALT16: 651 case SDP_TEXT_STR16: 652 case SDP_URL_STR16: 653 bt_put_unaligned(htons(length), (uint16_t *) ptr); 654 break; 655 case SDP_SEQ32: 656 case SDP_ALT32: 657 case SDP_TEXT_STR32: 658 case SDP_URL_STR32: 659 bt_put_unaligned(htonl(length), (uint32_t *) ptr); 660 break; 661 } 662} 663 664static int sdp_get_data_type(sdp_buf_t *buf, uint8_t dtd) 665{ 666 int data_type = 0; 667 668 data_type += sizeof(uint8_t); 669 670 switch (dtd) { 671 case SDP_SEQ8: 672 case SDP_TEXT_STR8: 673 case SDP_URL_STR8: 674 case SDP_ALT8: 675 data_type += sizeof(uint8_t); 676 break; 677 case SDP_SEQ16: 678 case SDP_TEXT_STR16: 679 case SDP_URL_STR16: 680 case SDP_ALT16: 681 data_type += sizeof(uint16_t); 682 break; 683 case SDP_SEQ32: 684 case SDP_TEXT_STR32: 685 case SDP_URL_STR32: 686 case SDP_ALT32: 687 data_type += sizeof(uint32_t); 688 break; 689 } 690 691 if (!buf->data) 692 buf->buf_size += data_type; 693 694 return data_type; 695} 696 697static int sdp_set_data_type(sdp_buf_t *buf, uint8_t dtd) 698{ 699 int data_type = 0; 700 uint8_t *p = buf->data + buf->data_size; 701 702 *p++ = dtd; 703 data_type = sdp_get_data_type(buf, dtd); 704 buf->data_size += data_type; 705 706 return data_type; 707} 708 709void sdp_set_attrid(sdp_buf_t *buf, uint16_t attr) 710{ 711 uint8_t *p = buf->data; 712 713 /* data type for attr */ 714 *p++ = SDP_UINT16; 715 buf->data_size = sizeof(uint8_t); 716 bt_put_unaligned(htons(attr), (uint16_t *) p); 717 p += sizeof(uint16_t); 718 buf->data_size += sizeof(uint16_t); 719} 720 721static int get_data_size(sdp_buf_t *buf, sdp_data_t *sdpdata) 722{ 723 sdp_data_t *d; 724 int n = 0; 725 726 for (d = sdpdata->val.dataseq; d; d = d->next) { 727 if (buf->data) 728 n += sdp_gen_pdu(buf, d); 729 else 730 n += sdp_gen_buffer(buf, d); 731 } 732 733 return n; 734} 735 736static int sdp_get_data_size(sdp_buf_t *buf, sdp_data_t *d) 737{ 738 uint32_t data_size = 0; 739 uint8_t dtd = d->dtd; 740 741 switch (dtd) { 742 case SDP_DATA_NIL: 743 break; 744 case SDP_UINT8: 745 data_size = sizeof(uint8_t); 746 break; 747 case SDP_UINT16: 748 data_size = sizeof(uint16_t); 749 break; 750 case SDP_UINT32: 751 data_size = sizeof(uint32_t); 752 break; 753 case SDP_UINT64: 754 data_size = sizeof(uint64_t); 755 break; 756 case SDP_UINT128: 757 data_size = sizeof(uint128_t); 758 break; 759 case SDP_INT8: 760 case SDP_BOOL: 761 data_size = sizeof(int8_t); 762 break; 763 case SDP_INT16: 764 data_size = sizeof(int16_t); 765 break; 766 case SDP_INT32: 767 data_size = sizeof(int32_t); 768 break; 769 case SDP_INT64: 770 data_size = sizeof(int64_t); 771 break; 772 case SDP_INT128: 773 data_size = sizeof(uint128_t); 774 break; 775 case SDP_TEXT_STR8: 776 case SDP_TEXT_STR16: 777 case SDP_TEXT_STR32: 778 case SDP_URL_STR8: 779 case SDP_URL_STR16: 780 case SDP_URL_STR32: 781 data_size = d->unitSize - sizeof(uint8_t); 782 break; 783 case SDP_SEQ8: 784 case SDP_SEQ16: 785 case SDP_SEQ32: 786 data_size = get_data_size(buf, d); 787 break; 788 case SDP_ALT8: 789 case SDP_ALT16: 790 case SDP_ALT32: 791 data_size = get_data_size(buf, d); 792 break; 793 case SDP_UUID16: 794 data_size = sizeof(uint16_t); 795 break; 796 case SDP_UUID32: 797 data_size = sizeof(uint32_t); 798 break; 799 case SDP_UUID128: 800 data_size = sizeof(uint128_t); 801 break; 802 default: 803 break; 804 } 805 806 if (!buf->data) 807 buf->buf_size += data_size; 808 809 return data_size; 810} 811 812static int sdp_gen_buffer(sdp_buf_t *buf, sdp_data_t *d) 813{ 814 int orig = buf->buf_size; 815 816 if (buf->buf_size == 0 && d->dtd == 0) { 817 /* create initial sequence */ 818 buf->buf_size += sizeof(uint8_t); 819 820 /* reserve space for sequence size */ 821 buf->buf_size += sizeof(uint8_t); 822 } 823 824 /* attribute length */ 825 buf->buf_size += sizeof(uint8_t) + sizeof(uint16_t); 826 827 sdp_get_data_type(buf, d->dtd); 828 sdp_get_data_size(buf, d); 829 830 if (buf->buf_size > UCHAR_MAX && d->dtd == SDP_SEQ8) 831 buf->buf_size += sizeof(uint8_t); 832 833 return buf->buf_size - orig; 834} 835 836int sdp_gen_pdu(sdp_buf_t *buf, sdp_data_t *d) 837{ 838 uint32_t pdu_size = 0, data_size = 0; 839 unsigned char *src = NULL, is_seq = 0, is_alt = 0; 840 uint8_t dtd = d->dtd; 841 uint16_t u16; 842 uint32_t u32; 843 uint64_t u64; 844 uint128_t u128; 845 uint8_t *seqp = buf->data + buf->data_size; 846 847 pdu_size = sdp_set_data_type(buf, dtd); 848 data_size = sdp_get_data_size(buf, d); 849 850 switch (dtd) { 851 case SDP_DATA_NIL: 852 break; 853 case SDP_UINT8: 854 src = &d->val.uint8; 855 break; 856 case SDP_UINT16: 857 u16 = htons(d->val.uint16); 858 src = (unsigned char *) &u16; 859 break; 860 case SDP_UINT32: 861 u32 = htonl(d->val.uint32); 862 src = (unsigned char *) &u32; 863 break; 864 case SDP_UINT64: 865 u64 = hton64(d->val.uint64); 866 src = (unsigned char *) &u64; 867 break; 868 case SDP_UINT128: 869 hton128(&d->val.uint128, &u128); 870 src = (unsigned char *) &u128; 871 break; 872 case SDP_INT8: 873 case SDP_BOOL: 874 src = (unsigned char *) &d->val.int8; 875 break; 876 case SDP_INT16: 877 u16 = htons(d->val.int16); 878 src = (unsigned char *) &u16; 879 break; 880 case SDP_INT32: 881 u32 = htonl(d->val.int32); 882 src = (unsigned char *) &u32; 883 break; 884 case SDP_INT64: 885 u64 = hton64(d->val.int64); 886 src = (unsigned char *) &u64; 887 break; 888 case SDP_INT128: 889 hton128(&d->val.int128, &u128); 890 src = (unsigned char *) &u128; 891 break; 892 case SDP_TEXT_STR8: 893 case SDP_TEXT_STR16: 894 case SDP_TEXT_STR32: 895 case SDP_URL_STR8: 896 case SDP_URL_STR16: 897 case SDP_URL_STR32: 898 src = (unsigned char *) d->val.str; 899 sdp_set_seq_len(seqp, data_size); 900 break; 901 case SDP_SEQ8: 902 case SDP_SEQ16: 903 case SDP_SEQ32: 904 is_seq = 1; 905 sdp_set_seq_len(seqp, data_size); 906 break; 907 case SDP_ALT8: 908 case SDP_ALT16: 909 case SDP_ALT32: 910 is_alt = 1; 911 sdp_set_seq_len(seqp, data_size); 912 break; 913 case SDP_UUID16: 914 u16 = htons(d->val.uuid.value.uuid16); 915 src = (unsigned char *) &u16; 916 break; 917 case SDP_UUID32: 918 u32 = htonl(d->val.uuid.value.uuid32); 919 src = (unsigned char *) &u32; 920 break; 921 case SDP_UUID128: 922 src = (unsigned char *) &d->val.uuid.value.uuid128; 923 break; 924 default: 925 break; 926 } 927 928 if (!is_seq && !is_alt) { 929 if (src && buf && buf->buf_size >= buf->data_size + data_size) { 930 memcpy(buf->data + buf->data_size, src, data_size); 931 buf->data_size += data_size; 932 } else if (dtd != SDP_DATA_NIL) { 933 SDPDBG("Gen PDU : Can't copy from invalid source or dest\n"); 934 } 935 } 936 937 pdu_size += data_size; 938 939 return pdu_size; 940} 941 942static void sdp_attr_pdu(void *value, void *udata) 943{ 944 sdp_append_to_pdu((sdp_buf_t *)udata, (sdp_data_t *)value); 945} 946 947static void sdp_attr_size(void *value, void *udata) 948{ 949 sdp_gen_buffer((sdp_buf_t *)udata, (sdp_data_t *)value); 950} 951 952int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *buf) 953{ 954 memset(buf, 0, sizeof(sdp_buf_t)); 955 sdp_list_foreach(rec->attrlist, sdp_attr_size, buf); 956 957 buf->data = malloc(buf->buf_size); 958 if (!buf->data) 959 return -ENOMEM; 960 buf->data_size = 0; 961 memset(buf->data, 0, buf->buf_size); 962 963 sdp_list_foreach(rec->attrlist, sdp_attr_pdu, buf); 964 965 return 0; 966} 967 968void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *d) 969{ 970 sdp_data_t *p = sdp_data_get(rec, attr); 971 972 if (p) { 973 rec->attrlist = sdp_list_remove(rec->attrlist, p); 974 sdp_data_free(p); 975 } 976 977 d->attrId = attr; 978 rec->attrlist = sdp_list_insert_sorted(rec->attrlist, d, sdp_attrid_comp_func); 979 980 if (attr == SDP_ATTR_SVCLASS_ID_LIST) 981 extract_svclass_uuid(d, &rec->svclass); 982} 983 984int sdp_attrid_comp_func(const void *key1, const void *key2) 985{ 986 const sdp_data_t *d1 = (const sdp_data_t *)key1; 987 const sdp_data_t *d2 = (const sdp_data_t *)key2; 988 989 if (d1 && d2) 990 return d1->attrId - d2->attrId; 991 return 0; 992} 993 994static void data_seq_free(sdp_data_t *seq) 995{ 996 sdp_data_t *d = seq->val.dataseq; 997 998 while (d) { 999 sdp_data_t *next = d->next; 1000 sdp_data_free(d); 1001 d = next; 1002 } 1003} 1004 1005void sdp_data_free(sdp_data_t *d) 1006{ 1007 switch (d->dtd) { 1008 case SDP_SEQ8: 1009 case SDP_SEQ16: 1010 case SDP_SEQ32: 1011 data_seq_free(d); 1012 break; 1013 case SDP_URL_STR8: 1014 case SDP_URL_STR16: 1015 case SDP_URL_STR32: 1016 case SDP_TEXT_STR8: 1017 case SDP_TEXT_STR16: 1018 case SDP_TEXT_STR32: 1019 free(d->val.str); 1020 break; 1021 } 1022 free(d); 1023} 1024 1025int sdp_uuid_extract(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned) 1026{ 1027 uint8_t type; 1028 1029 if (bufsize < (int) sizeof(uint8_t)) { 1030 SDPERR("Unexpected end of packet"); 1031 return -1; 1032 } 1033 1034 type = *(const uint8_t *) p; 1035 1036 if (!SDP_IS_UUID(type)) { 1037 SDPERR("Unknown data type : %d expecting a svc UUID\n", type); 1038 return -1; 1039 } 1040 p += sizeof(uint8_t); 1041 *scanned += sizeof(uint8_t); 1042 bufsize -= sizeof(uint8_t); 1043 if (type == SDP_UUID16) { 1044 if (bufsize < (int) sizeof(uint16_t)) { 1045 SDPERR("Not enough room for 16-bit UUID"); 1046 return -1; 1047 } 1048 sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p))); 1049 *scanned += sizeof(uint16_t); 1050 p += sizeof(uint16_t); 1051 } else if (type == SDP_UUID32) { 1052 if (bufsize < (int) sizeof(uint32_t)) { 1053 SDPERR("Not enough room for 32-bit UUID"); 1054 return -1; 1055 } 1056 sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p))); 1057 *scanned += sizeof(uint32_t); 1058 p += sizeof(uint32_t); 1059 } else { 1060 if (bufsize < (int) sizeof(uint128_t)) { 1061 SDPERR("Not enough room for 128-bit UUID"); 1062 return -1; 1063 } 1064 sdp_uuid128_create(uuid, p); 1065 *scanned += sizeof(uint128_t); 1066 p += sizeof(uint128_t); 1067 } 1068 return 0; 1069} 1070 1071static sdp_data_t *extract_int(const void *p, int bufsize, int *len) 1072{ 1073 sdp_data_t *d; 1074 1075 if (bufsize < (int) sizeof(uint8_t)) { 1076 SDPERR("Unexpected end of packet"); 1077 return NULL; 1078 } 1079 1080 d = malloc(sizeof(sdp_data_t)); 1081 1082 SDPDBG("Extracting integer\n"); 1083 memset(d, 0, sizeof(sdp_data_t)); 1084 d->dtd = *(uint8_t *) p; 1085 p += sizeof(uint8_t); 1086 *len += sizeof(uint8_t); 1087 bufsize -= sizeof(uint8_t); 1088 1089 switch (d->dtd) { 1090 case SDP_DATA_NIL: 1091 break; 1092 case SDP_BOOL: 1093 case SDP_INT8: 1094 case SDP_UINT8: 1095 if (bufsize < (int) sizeof(uint8_t)) { 1096 SDPERR("Unexpected end of packet"); 1097 free(d); 1098 return NULL; 1099 } 1100 *len += sizeof(uint8_t); 1101 d->val.uint8 = *(uint8_t *) p; 1102 break; 1103 case SDP_INT16: 1104 case SDP_UINT16: 1105 if (bufsize < (int) sizeof(uint16_t)) { 1106 SDPERR("Unexpected end of packet"); 1107 free(d); 1108 return NULL; 1109 } 1110 *len += sizeof(uint16_t); 1111 d->val.uint16 = ntohs(bt_get_unaligned((uint16_t *) p)); 1112 break; 1113 case SDP_INT32: 1114 case SDP_UINT32: 1115 if (bufsize < (int) sizeof(uint32_t)) { 1116 SDPERR("Unexpected end of packet"); 1117 free(d); 1118 return NULL; 1119 } 1120 *len += sizeof(uint32_t); 1121 d->val.uint32 = ntohl(bt_get_unaligned((uint32_t *) p)); 1122 break; 1123 case SDP_INT64: 1124 case SDP_UINT64: 1125 if (bufsize < (int) sizeof(uint64_t)) { 1126 SDPERR("Unexpected end of packet"); 1127 free(d); 1128 return NULL; 1129 } 1130 *len += sizeof(uint64_t); 1131 d->val.uint64 = ntoh64(bt_get_unaligned((uint64_t *) p)); 1132 break; 1133 case SDP_INT128: 1134 case SDP_UINT128: 1135 if (bufsize < (int) sizeof(uint128_t)) { 1136 SDPERR("Unexpected end of packet"); 1137 free(d); 1138 return NULL; 1139 } 1140 *len += sizeof(uint128_t); 1141 ntoh128((uint128_t *) p, &d->val.uint128); 1142 break; 1143 default: 1144 free(d); 1145 d = NULL; 1146 } 1147 return d; 1148} 1149 1150static sdp_data_t *extract_uuid(const uint8_t *p, int bufsize, int *len, 1151 sdp_record_t *rec) 1152{ 1153 sdp_data_t *d = malloc(sizeof(sdp_data_t)); 1154 1155 SDPDBG("Extracting UUID"); 1156 memset(d, 0, sizeof(sdp_data_t)); 1157 if (sdp_uuid_extract(p, bufsize, &d->val.uuid, len) < 0) { 1158 free(d); 1159 return NULL; 1160 } 1161 d->dtd = *(uint8_t *) p; 1162 if (rec) 1163 sdp_pattern_add_uuid(rec, &d->val.uuid); 1164 return d; 1165} 1166 1167/* 1168 * Extract strings from the PDU (could be service description and similar info) 1169 */ 1170static sdp_data_t *extract_str(const void *p, int bufsize, int *len) 1171{ 1172 char *s; 1173 int n; 1174 sdp_data_t *d; 1175 1176 if (bufsize < (int) sizeof(uint8_t)) { 1177 SDPERR("Unexpected end of packet"); 1178 return NULL; 1179 } 1180 1181 d = malloc(sizeof(sdp_data_t)); 1182 1183 memset(d, 0, sizeof(sdp_data_t)); 1184 d->dtd = *(uint8_t *) p; 1185 p += sizeof(uint8_t); 1186 *len += sizeof(uint8_t); 1187 bufsize -= sizeof(uint8_t); 1188 1189 switch (d->dtd) { 1190 case SDP_TEXT_STR8: 1191 case SDP_URL_STR8: 1192 if (bufsize < (int) sizeof(uint8_t)) { 1193 SDPERR("Unexpected end of packet"); 1194 free(d); 1195 return NULL; 1196 } 1197 n = *(uint8_t *) p; 1198 p += sizeof(uint8_t); 1199 *len += sizeof(uint8_t); 1200 bufsize -= sizeof(uint8_t); 1201 break; 1202 case SDP_TEXT_STR16: 1203 case SDP_URL_STR16: 1204 if (bufsize < (int) sizeof(uint16_t)) { 1205 SDPERR("Unexpected end of packet"); 1206 free(d); 1207 return NULL; 1208 } 1209 n = ntohs(bt_get_unaligned((uint16_t *) p)); 1210 p += sizeof(uint16_t); 1211 *len += sizeof(uint16_t) + n; 1212 bufsize -= sizeof(uint16_t); 1213 break; 1214 default: 1215 SDPERR("Sizeof text string > UINT16_MAX\n"); 1216 free(d); 1217 return 0; 1218 } 1219 1220 if (bufsize < n) { 1221 SDPERR("String too long to fit in packet"); 1222 free(d); 1223 return NULL; 1224 } 1225 1226 s = malloc(n + 1); 1227 if (!s) { 1228 SDPERR("Not enough memory for incoming string"); 1229 free(d); 1230 return NULL; 1231 } 1232 memset(s, 0, n + 1); 1233 memcpy(s, p, n); 1234 1235 *len += n; 1236 1237 SDPDBG("Len : %d\n", n); 1238 SDPDBG("Str : %s\n", s); 1239 1240 d->val.str = s; 1241 d->unitSize = n + sizeof(uint8_t); 1242 return d; 1243} 1244 1245/* 1246 * Extract the sequence type and its length, and return offset into buf 1247 * or 0 on failure. 1248 */ 1249int sdp_extract_seqtype(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size) 1250{ 1251 uint8_t dtd; 1252 int scanned = sizeof(uint8_t); 1253 1254 if (bufsize < (int) sizeof(uint8_t)) { 1255 SDPERR("Unexpected end of packet"); 1256 return 0; 1257 } 1258 1259 dtd = *(uint8_t *) buf; 1260 buf += sizeof(uint8_t); 1261 bufsize -= sizeof(uint8_t); 1262 *dtdp = dtd; 1263 switch (dtd) { 1264 case SDP_SEQ8: 1265 case SDP_ALT8: 1266 if (bufsize < (int) sizeof(uint8_t)) { 1267 SDPERR("Unexpected end of packet"); 1268 return 0; 1269 } 1270 *size = *(uint8_t *) buf; 1271 scanned += sizeof(uint8_t); 1272 break; 1273 case SDP_SEQ16: 1274 case SDP_ALT16: 1275 if (bufsize < (int) sizeof(uint16_t)) { 1276 SDPERR("Unexpected end of packet"); 1277 return 0; 1278 } 1279 *size = ntohs(bt_get_unaligned((uint16_t *) buf)); 1280 scanned += sizeof(uint16_t); 1281 break; 1282 case SDP_SEQ32: 1283 case SDP_ALT32: 1284 if (bufsize < (int) sizeof(uint32_t)) { 1285 SDPERR("Unexpected end of packet"); 1286 return 0; 1287 } 1288 *size = ntohl(bt_get_unaligned((uint32_t *) buf)); 1289 scanned += sizeof(uint32_t); 1290 break; 1291 default: 1292 SDPERR("Unknown sequence type, aborting\n"); 1293 return 0; 1294 } 1295 return scanned; 1296} 1297 1298static sdp_data_t *extract_seq(const void *p, int bufsize, int *len, 1299 sdp_record_t *rec) 1300{ 1301 int seqlen, n = 0; 1302 sdp_data_t *curr, *prev; 1303 sdp_data_t *d = malloc(sizeof(sdp_data_t)); 1304 1305 SDPDBG("Extracting SEQ"); 1306 memset(d, 0, sizeof(sdp_data_t)); 1307 *len = sdp_extract_seqtype(p, bufsize, &d->dtd, &seqlen); 1308 SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen); 1309 1310 if (*len == 0) 1311 return d; 1312 1313 if (*len > bufsize) { 1314 SDPERR("Packet not big enough to hold sequence."); 1315 free(d); 1316 return NULL; 1317 } 1318 1319 p += *len; 1320 bufsize -= *len; 1321 prev = NULL; 1322 while (n < seqlen) { 1323 int attrlen = 0; 1324 curr = sdp_extract_attr(p, bufsize, &attrlen, rec); 1325 if (curr == NULL) 1326 break; 1327 1328 if (prev) 1329 prev->next = curr; 1330 else 1331 d->val.dataseq = curr; 1332 prev = curr; 1333 p += attrlen; 1334 n += attrlen; 1335 bufsize -= attrlen; 1336 1337 SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen); 1338 } 1339 1340 *len += n; 1341 return d; 1342} 1343 1344sdp_data_t *sdp_extract_attr(const uint8_t *p, int bufsize, int *size, 1345 sdp_record_t *rec) 1346{ 1347 sdp_data_t *elem; 1348 int n = 0; 1349 uint8_t dtd; 1350 1351 if (bufsize < (int) sizeof(uint8_t)) { 1352 SDPERR("Unexpected end of packet"); 1353 return NULL; 1354 } 1355 1356 dtd = *(const uint8_t *)p; 1357 1358 SDPDBG("extract_attr: dtd=0x%x", dtd); 1359 switch (dtd) { 1360 case SDP_DATA_NIL: 1361 case SDP_BOOL: 1362 case SDP_UINT8: 1363 case SDP_UINT16: 1364 case SDP_UINT32: 1365 case SDP_UINT64: 1366 case SDP_UINT128: 1367 case SDP_INT8: 1368 case SDP_INT16: 1369 case SDP_INT32: 1370 case SDP_INT64: 1371 case SDP_INT128: 1372 elem = extract_int(p, bufsize, &n); 1373 break; 1374 case SDP_UUID16: 1375 case SDP_UUID32: 1376 case SDP_UUID128: 1377 elem = extract_uuid(p, bufsize, &n, rec); 1378 break; 1379 case SDP_TEXT_STR8: 1380 case SDP_TEXT_STR16: 1381 case SDP_TEXT_STR32: 1382 case SDP_URL_STR8: 1383 case SDP_URL_STR16: 1384 case SDP_URL_STR32: 1385 elem = extract_str(p, bufsize, &n); 1386 break; 1387 case SDP_SEQ8: 1388 case SDP_SEQ16: 1389 case SDP_SEQ32: 1390 case SDP_ALT8: 1391 case SDP_ALT16: 1392 case SDP_ALT32: 1393 elem = extract_seq(p, bufsize, &n, rec); 1394 break; 1395 default: 1396 SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd); 1397 return NULL; 1398 } 1399 *size += n; 1400 return elem; 1401} 1402 1403#ifdef SDP_DEBUG 1404static void attr_print_func(void *value, void *userData) 1405{ 1406 sdp_data_t *d = (sdp_data_t *)value; 1407 1408 SDPDBG("=====================================\n"); 1409 SDPDBG("ATTRIBUTE IDENTIFIER : 0x%x\n", d->attrId); 1410 SDPDBG("ATTRIBUTE VALUE PTR : 0x%x\n", (uint32_t)value); 1411 if (d) 1412 sdp_data_print(d); 1413 else 1414 SDPDBG("NULL value\n"); 1415 SDPDBG("=====================================\n"); 1416} 1417 1418void sdp_print_service_attr(sdp_list_t *svcAttrList) 1419{ 1420 SDPDBG("Printing service attr list %p\n", svcAttrList); 1421 sdp_list_foreach(svcAttrList, attr_print_func, NULL); 1422 SDPDBG("Printed service attr list %p\n", svcAttrList); 1423} 1424#endif 1425 1426sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int bufsize, int *scanned) 1427{ 1428 int extracted = 0, seqlen = 0; 1429 uint8_t dtd; 1430 uint16_t attr; 1431 sdp_record_t *rec = sdp_record_alloc(); 1432 const uint8_t *p = buf; 1433 1434 *scanned = sdp_extract_seqtype(buf, bufsize, &dtd, &seqlen); 1435 p += *scanned; 1436 bufsize -= *scanned; 1437 rec->attrlist = NULL; 1438 1439 while (extracted < seqlen && bufsize > 0) { 1440 int n = sizeof(uint8_t), attrlen = 0; 1441 sdp_data_t *data = NULL; 1442 1443 SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", 1444 seqlen, extracted); 1445 1446 if (bufsize < n + (int) sizeof(uint16_t)) { 1447 SDPERR("Unexpected end of packet"); 1448 break; 1449 } 1450 1451 dtd = *(uint8_t *) p; 1452 attr = ntohs(bt_get_unaligned((uint16_t *) (p + n))); 1453 n += sizeof(uint16_t); 1454 1455 SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr); 1456 1457 data = sdp_extract_attr(p + n, bufsize - n, &attrlen, rec); 1458 1459 SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen); 1460 1461 n += attrlen; 1462 if (data == NULL) { 1463 SDPDBG("Terminating extraction of attributes"); 1464 break; 1465 } 1466 1467 if (attr == SDP_ATTR_RECORD_HANDLE) 1468 rec->handle = data->val.uint32; 1469 1470 if (attr == SDP_ATTR_SVCLASS_ID_LIST) 1471 extract_svclass_uuid(data, &rec->svclass); 1472 1473 extracted += n; 1474 p += n; 1475 bufsize -= n; 1476 sdp_attr_replace(rec, attr, data); 1477 1478 SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d", 1479 seqlen, extracted); 1480 } 1481#ifdef SDP_DEBUG 1482 SDPDBG("Successful extracting of Svc Rec attributes\n"); 1483 sdp_print_service_attr(rec->attrlist); 1484#endif 1485 *scanned += seqlen; 1486 return rec; 1487} 1488 1489static void sdp_copy_pattern(void *value, void *udata) 1490{ 1491 uuid_t *uuid = value; 1492 sdp_record_t *rec = udata; 1493 1494 sdp_pattern_add_uuid(rec, uuid); 1495} 1496 1497static void *sdp_data_value(sdp_data_t *data, uint32_t *len) 1498{ 1499 void *val = NULL; 1500 1501 switch (data->dtd) { 1502 case SDP_DATA_NIL: 1503 break; 1504 case SDP_UINT8: 1505 val = &data->val.uint8; 1506 break; 1507 case SDP_INT8: 1508 case SDP_BOOL: 1509 val = &data->val.int8; 1510 break; 1511 case SDP_UINT16: 1512 val = &data->val.uint16; 1513 break; 1514 case SDP_INT16: 1515 val = &data->val.int16; 1516 break; 1517 case SDP_UINT32: 1518 val = &data->val.uint32; 1519 break; 1520 case SDP_INT32: 1521 val = &data->val.int32; 1522 break; 1523 case SDP_INT64: 1524 val = &data->val.int64; 1525 break; 1526 case SDP_UINT64: 1527 val = &data->val.uint64; 1528 break; 1529 case SDP_UINT128: 1530 val = &data->val.uint128; 1531 break; 1532 case SDP_INT128: 1533 val = &data->val.int128; 1534 break; 1535 case SDP_UUID16: 1536 val = &data->val.uuid.value.uuid16; 1537 break; 1538 case SDP_UUID32: 1539 val = &data->val.uuid.value.uuid32; 1540 break; 1541 case SDP_UUID128: 1542 val = &data->val.uuid.value.uuid128; 1543 break; 1544 case SDP_URL_STR8: 1545 case SDP_URL_STR16: 1546 case SDP_TEXT_STR8: 1547 case SDP_TEXT_STR16: 1548 case SDP_URL_STR32: 1549 case SDP_TEXT_STR32: 1550 val = data->val.str; 1551 if (len) 1552 *len = data->unitSize - 1; 1553 break; 1554 case SDP_ALT8: 1555 case SDP_ALT16: 1556 case SDP_ALT32: 1557 case SDP_SEQ8: 1558 case SDP_SEQ16: 1559 case SDP_SEQ32: 1560 val = sdp_copy_seq(data->val.dataseq); 1561 break; 1562 } 1563 1564 return val; 1565} 1566 1567static sdp_data_t *sdp_copy_seq(sdp_data_t *data) 1568{ 1569 sdp_data_t *tmp, *seq = NULL, *cur = NULL; 1570 1571 for (tmp = data; tmp; tmp = tmp->next) { 1572 sdp_data_t *datatmp; 1573 void *value; 1574 1575 value = sdp_data_value(tmp, NULL); 1576 datatmp = sdp_data_alloc_with_length(tmp->dtd, value, 1577 tmp->unitSize); 1578 1579 if (cur) 1580 cur->next = datatmp; 1581 else 1582 seq = datatmp; 1583 1584 cur = datatmp; 1585 } 1586 1587 return seq; 1588} 1589 1590static void sdp_copy_attrlist(void *value, void *udata) 1591{ 1592 sdp_data_t *data = value; 1593 sdp_record_t *rec = udata; 1594 void *val; 1595 uint32_t len = 0; 1596 1597 val = sdp_data_value(data, &len); 1598 1599 if (!len) 1600 sdp_attr_add_new(rec, data->attrId, data->dtd, val); 1601 else 1602 sdp_attr_add_new_with_length(rec, data->attrId, 1603 data->dtd, val, len); 1604} 1605 1606sdp_record_t *sdp_copy_record(sdp_record_t *rec) 1607{ 1608 sdp_record_t *cpy; 1609 1610 cpy = sdp_record_alloc(); 1611 1612 cpy->handle = rec->handle; 1613 1614 sdp_list_foreach(rec->pattern, sdp_copy_pattern, cpy); 1615 sdp_list_foreach(rec->attrlist, sdp_copy_attrlist, cpy); 1616 1617 cpy->svclass = rec->svclass; 1618 1619 return cpy; 1620} 1621 1622#ifdef SDP_DEBUG 1623static void print_dataseq(sdp_data_t *p) 1624{ 1625 sdp_data_t *d; 1626 1627 for (d = p; d; d = d->next) 1628 sdp_data_print(d); 1629} 1630#endif 1631 1632void sdp_record_print(const sdp_record_t *rec) 1633{ 1634 sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); 1635 if (d) 1636 printf("Service Name: %.*s\n", d->unitSize, d->val.str); 1637 d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY); 1638 if (d) 1639 printf("Service Description: %.*s\n", d->unitSize, d->val.str); 1640 d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY); 1641 if (d) 1642 printf("Service Provider: %.*s\n", d->unitSize, d->val.str); 1643} 1644 1645#ifdef SDP_DEBUG 1646void sdp_data_print(sdp_data_t *d) 1647{ 1648 switch (d->dtd) { 1649 case SDP_DATA_NIL: 1650 SDPDBG("NIL\n"); 1651 break; 1652 case SDP_BOOL: 1653 case SDP_UINT8: 1654 case SDP_UINT16: 1655 case SDP_UINT32: 1656 case SDP_UINT64: 1657 case SDP_UINT128: 1658 case SDP_INT8: 1659 case SDP_INT16: 1660 case SDP_INT32: 1661 case SDP_INT64: 1662 case SDP_INT128: 1663 SDPDBG("Integer : 0x%x\n", d->val.uint32); 1664 break; 1665 case SDP_UUID16: 1666 case SDP_UUID32: 1667 case SDP_UUID128: 1668 SDPDBG("UUID\n"); 1669 sdp_uuid_print(&d->val.uuid); 1670 break; 1671 case SDP_TEXT_STR8: 1672 case SDP_TEXT_STR16: 1673 case SDP_TEXT_STR32: 1674 SDPDBG("Text : %s\n", d->val.str); 1675 break; 1676 case SDP_URL_STR8: 1677 case SDP_URL_STR16: 1678 case SDP_URL_STR32: 1679 SDPDBG("URL : %s\n", d->val.str); 1680 break; 1681 case SDP_SEQ8: 1682 case SDP_SEQ16: 1683 case SDP_SEQ32: 1684 print_dataseq(d->val.dataseq); 1685 break; 1686 case SDP_ALT8: 1687 case SDP_ALT16: 1688 case SDP_ALT32: 1689 SDPDBG("Data Sequence Alternates\n"); 1690 print_dataseq(d->val.dataseq); 1691 break; 1692 } 1693} 1694#endif 1695 1696sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attrId) 1697{ 1698 if (rec->attrlist) { 1699 sdp_data_t sdpTemplate; 1700 sdp_list_t *p; 1701 1702 sdpTemplate.attrId = attrId; 1703 p = sdp_list_find(rec->attrlist, &sdpTemplate, sdp_attrid_comp_func); 1704 if (p) 1705 return (sdp_data_t *)p->data; 1706 } 1707 return NULL; 1708} 1709 1710static int sdp_send_req(sdp_session_t *session, uint8_t *buf, uint32_t size) 1711{ 1712 uint32_t sent = 0; 1713 1714 while (sent < size) { 1715 int n = send(session->sock, buf + sent, size - sent, 0); 1716 if (n < 0) 1717 return -1; 1718 sent += n; 1719 } 1720 return 0; 1721} 1722 1723static int sdp_read_rsp(sdp_session_t *session, uint8_t *buf, uint32_t size) 1724{ 1725 fd_set readFds; 1726 struct timeval timeout = { SDP_RESPONSE_TIMEOUT, 0 }; 1727 1728 FD_ZERO(&readFds); 1729 FD_SET(session->sock, &readFds); 1730 SDPDBG("Waiting for response\n"); 1731 if (select(session->sock + 1, &readFds, NULL, NULL, &timeout) == 0) { 1732 SDPERR("Client timed out\n"); 1733 errno = ETIMEDOUT; 1734 return -1; 1735 } 1736 return recv(session->sock, buf, size, 0); 1737} 1738 1739/* 1740 * generic send request, wait for response method. 1741 */ 1742int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *reqbuf, 1743 uint8_t *rspbuf, uint32_t reqsize, uint32_t *rspsize) 1744{ 1745 int n; 1746 sdp_pdu_hdr_t *reqhdr = (sdp_pdu_hdr_t *)reqbuf; 1747 sdp_pdu_hdr_t *rsphdr = (sdp_pdu_hdr_t *)rspbuf; 1748 1749 SDPDBG(""); 1750 if (0 > sdp_send_req(session, reqbuf, reqsize)) { 1751 SDPERR("Error sending data:%s", strerror(errno)); 1752 return -1; 1753 } 1754 n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); 1755 if (0 > n) 1756 return -1; 1757 SDPDBG("Read : %d\n", n); 1758 if (n == 0 || reqhdr->tid != rsphdr->tid) { 1759 errno = EPROTO; 1760 return -1; 1761 } 1762 *rspsize = n; 1763 return 0; 1764} 1765 1766/* 1767 * singly-linked lists (after openobex implementation) 1768 */ 1769sdp_list_t *sdp_list_append(sdp_list_t *p, void *d) 1770{ 1771 sdp_list_t *q, *n = malloc(sizeof(sdp_list_t)); 1772 1773 if (!n) 1774 return 0; 1775 1776 n->data = d; 1777 n->next = 0; 1778 1779 if (!p) 1780 return n; 1781 1782 for (q = p; q->next; q = q->next); 1783 q->next = n; 1784 1785 return p; 1786} 1787 1788sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d) 1789{ 1790 sdp_list_t *p, *q; 1791 1792 for (q = 0, p = list; p; q = p, p = p->next) 1793 if (p->data == d) { 1794 if (q) 1795 q->next = p->next; 1796 else 1797 list = p->next; 1798 free(p); 1799 break; 1800 } 1801 1802 return list; 1803} 1804 1805sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *d, 1806 sdp_comp_func_t f) 1807{ 1808 sdp_list_t *q, *p, *n; 1809 1810 n = malloc(sizeof(sdp_list_t)); 1811 if (!n) 1812 return 0; 1813 n->data = d; 1814 for (q = 0, p = list; p; q = p, p = p->next) 1815 if (f(p->data, d) >= 0) 1816 break; 1817 // insert between q and p; if !q insert at head 1818 if (q) 1819 q->next = n; 1820 else 1821 list = n; 1822 n->next = p; 1823 return list; 1824} 1825 1826/* 1827 * Every element of the list points to things which need 1828 * to be free()'d. This method frees the list's contents 1829 */ 1830void sdp_list_free(sdp_list_t *list, sdp_free_func_t f) 1831{ 1832 sdp_list_t *next; 1833 while (list) { 1834 next = list->next; 1835 if (f) 1836 f(list->data); 1837 free(list); 1838 list = next; 1839 } 1840} 1841 1842static inline int __find_port(sdp_data_t *seq, int proto) 1843{ 1844 if (!seq || !seq->next) 1845 return 0; 1846 1847 if (SDP_IS_UUID(seq->dtd) && sdp_uuid_to_proto(&seq->val.uuid) == proto) { 1848 seq = seq->next; 1849 switch (seq->dtd) { 1850 case SDP_UINT8: 1851 return seq->val.uint8; 1852 case SDP_UINT16: 1853 return seq->val.uint16; 1854 } 1855 } 1856 return 0; 1857} 1858 1859int sdp_get_proto_port(const sdp_list_t *list, int proto) 1860{ 1861 if (proto != L2CAP_UUID && proto != RFCOMM_UUID) { 1862 errno = EINVAL; 1863 return -1; 1864 } 1865 1866 for (; list; list = list->next) { 1867 sdp_list_t *p; 1868 for (p = list->data; p; p = p->next) { 1869 sdp_data_t *seq = (sdp_data_t *) p->data; 1870 int port = __find_port(seq, proto); 1871 if (port) 1872 return port; 1873 } 1874 } 1875 return 0; 1876} 1877 1878sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto) 1879{ 1880 for (; list; list = list->next) { 1881 sdp_list_t *p; 1882 for (p = list->data; p; p = p->next) { 1883 sdp_data_t *seq = (sdp_data_t *) p->data; 1884 if (SDP_IS_UUID(seq->dtd) && 1885 sdp_uuid_to_proto(&seq->val.uuid) == proto) 1886 return seq->next; 1887 } 1888 } 1889 return NULL; 1890} 1891 1892int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap) 1893{ 1894 sdp_data_t *pdlist, *curr; 1895 sdp_list_t *ap = 0; 1896 1897 pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST); 1898 if (pdlist == NULL) { 1899 errno = ENODATA; 1900 return -1; 1901 } 1902 SDPDBG("AP type : 0%x\n", pdlist->dtd); 1903 1904 for (; pdlist; pdlist = pdlist->next) { 1905 sdp_list_t *pds = 0; 1906 for (curr = pdlist->val.dataseq; curr; curr = curr->next) 1907 pds = sdp_list_append(pds, curr->val.dataseq); 1908 ap = sdp_list_append(ap, pds); 1909 } 1910 *pap = ap; 1911 return 0; 1912} 1913 1914int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap) 1915{ 1916 sdp_data_t *pdlist, *curr; 1917 sdp_list_t *ap = 0; 1918 1919 pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); 1920 if (pdlist == NULL) { 1921 errno = ENODATA; 1922 return -1; 1923 } 1924 SDPDBG("AP type : 0%x\n", pdlist->dtd); 1925 1926 pdlist = pdlist->val.dataseq; 1927 1928 for (; pdlist; pdlist = pdlist->next) { 1929 sdp_list_t *pds = 0; 1930 for (curr = pdlist->val.dataseq; curr; curr = curr->next) 1931 pds = sdp_list_append(pds, curr->val.dataseq); 1932 ap = sdp_list_append(ap, pds); 1933 } 1934 *pap = ap; 1935 return 0; 1936} 1937 1938int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, 1939 sdp_list_t **seqp) 1940{ 1941 sdp_data_t *sdpdata = sdp_data_get(rec, attr); 1942 1943 *seqp = NULL; 1944 if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) { 1945 sdp_data_t *d; 1946 for (d = sdpdata->val.dataseq; d; d = d->next) { 1947 uuid_t *u; 1948 if (d->dtd < SDP_UUID16 || d->dtd > SDP_UUID128) 1949 goto fail; 1950 1951 u = malloc(sizeof(uuid_t)); 1952 memset(u, 0, sizeof(uuid_t)); 1953 *u = d->val.uuid; 1954 *seqp = sdp_list_append(*seqp, u); 1955 } 1956 return 0; 1957 } 1958fail: 1959 sdp_list_free(*seqp, free); 1960 errno = EINVAL; 1961 return -1; 1962} 1963 1964int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq) 1965{ 1966 int status = 0, i, len; 1967 void **dtds, **values; 1968 uint8_t uuid16 = SDP_UUID16; 1969 uint8_t uuid32 = SDP_UUID32; 1970 uint8_t uuid128 = SDP_UUID128; 1971 sdp_list_t *p; 1972 1973 len = sdp_list_len(seq); 1974 if (!seq || len == 0) 1975 return -1; 1976 dtds = (void **)malloc(len * sizeof(void *)); 1977 values = (void **)malloc(len * sizeof(void *)); 1978 for (p = seq, i = 0; i < len; i++, p = p->next) { 1979 uuid_t *uuid = (uuid_t *)p->data; 1980 if (uuid) 1981 switch (uuid->type) { 1982 case SDP_UUID16: 1983 dtds[i] = &uuid16; 1984 values[i] = &uuid->value.uuid16; 1985 break; 1986 case SDP_UUID32: 1987 dtds[i] = &uuid32; 1988 values[i] = &uuid->value.uuid32; 1989 break; 1990 case SDP_UUID128: 1991 dtds[i] = &uuid128; 1992 values[i] = &uuid->value.uuid128; 1993 break; 1994 default: 1995 status = -1; 1996 break; 1997 } 1998 else { 1999 status = -1; 2000 break; 2001 } 2002 } 2003 if (status == 0) { 2004 sdp_data_t *data = sdp_seq_alloc(dtds, values, len); 2005 sdp_attr_replace(rec, aid, data); 2006 sdp_pattern_add_uuidseq(rec, seq); 2007 } 2008 free(dtds); 2009 free(values); 2010 return status; 2011} 2012 2013int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq) 2014{ 2015 sdp_lang_attr_t *lang; 2016 sdp_data_t *sdpdata, *curr_data; 2017 2018 *langSeq = NULL; 2019 sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST); 2020 if (sdpdata == NULL) { 2021 errno = ENODATA; 2022 return -1; 2023 } 2024 curr_data = sdpdata->val.dataseq; 2025 while (curr_data) { 2026 sdp_data_t *pCode = curr_data; 2027 sdp_data_t *pEncoding = pCode->next; 2028 sdp_data_t *pOffset = pEncoding->next; 2029 if (pEncoding && pOffset) { 2030 lang = malloc(sizeof(sdp_lang_attr_t)); 2031 lang->code_ISO639 = pCode->val.uint16; 2032 lang->encoding = pEncoding->val.uint16; 2033 lang->base_offset = pOffset->val.uint16; 2034 SDPDBG("code_ISO639 : 0x%02x\n", lang->code_ISO639); 2035 SDPDBG("encoding : 0x%02x\n", lang->encoding); 2036 SDPDBG("base_offfset : 0x%02x\n", lang->base_offset); 2037 *langSeq = sdp_list_append(*langSeq, lang); 2038 } 2039 curr_data = pOffset->next; 2040 } 2041 return 0; 2042} 2043 2044int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq) 2045{ 2046 sdp_profile_desc_t *profDesc; 2047 sdp_data_t *sdpdata, *seq; 2048 2049 *profDescSeq = NULL; 2050 sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST); 2051 if (!sdpdata || !sdpdata->val.dataseq) { 2052 errno = ENODATA; 2053 return -1; 2054 } 2055 for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) { 2056 uuid_t *uuid = NULL; 2057 uint16_t version = 0x100; 2058 2059 if (SDP_IS_UUID(seq->dtd)) { 2060 uuid = &seq->val.uuid; 2061 } else { 2062 sdp_data_t *puuid = seq->val.dataseq; 2063 sdp_data_t *pVnum = seq->val.dataseq->next; 2064 if (puuid && pVnum) { 2065 uuid = &puuid->val.uuid; 2066 version = pVnum->val.uint16; 2067 } 2068 } 2069 2070 if (uuid != NULL) { 2071 profDesc = malloc(sizeof(sdp_profile_desc_t)); 2072 profDesc->uuid = *uuid; 2073 profDesc->version = version; 2074#ifdef SDP_DEBUG 2075 sdp_uuid_print(&profDesc->uuid); 2076 SDPDBG("Vnum : 0x%04x\n", profDesc->version); 2077#endif 2078 *profDescSeq = sdp_list_append(*profDescSeq, profDesc); 2079 } 2080 } 2081 return 0; 2082} 2083 2084int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16) 2085{ 2086 sdp_data_t *d, *curr; 2087 2088 *u16 = NULL; 2089 d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST); 2090 if (d == NULL) { 2091 errno = ENODATA; 2092 return -1; 2093 } 2094 for (curr = d->val.dataseq; curr; curr = curr->next) 2095 *u16 = sdp_list_append(*u16, &curr->val.uint16); 2096 return 0; 2097} 2098 2099/* flexible extraction of basic attributes - Jean II */ 2100/* How do we expect caller to extract predefined data sequences? */ 2101int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value) 2102{ 2103 sdp_data_t *sdpdata = sdp_data_get(rec, attrid); 2104 2105 if (sdpdata) 2106 /* Verify that it is what the caller expects */ 2107 if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 || 2108 sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 || 2109 sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 || 2110 sdpdata->dtd == SDP_INT32) { 2111 *value = sdpdata->val.uint32; 2112 return 0; 2113 } 2114 errno = EINVAL; 2115 return -1; 2116} 2117 2118int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, 2119 int valuelen) 2120{ 2121 sdp_data_t *sdpdata = sdp_data_get(rec, attrid); 2122 if (sdpdata) 2123 /* Verify that it is what the caller expects */ 2124 if (sdpdata->dtd == SDP_TEXT_STR8 || 2125 sdpdata->dtd == SDP_TEXT_STR16 || 2126 sdpdata->dtd == SDP_TEXT_STR32) 2127 if ((int) strlen(sdpdata->val.str) < valuelen) { 2128 strcpy(value, sdpdata->val.str); 2129 return 0; 2130 } 2131 errno = EINVAL; 2132 return -1; 2133} 2134 2135#define get_basic_attr(attrID, pAttrValue, fieldName) \ 2136 sdp_data_t *data = sdp_data_get(rec, attrID); \ 2137 if (data) { \ 2138 *pAttrValue = data->val.fieldName; \ 2139 return 0; \ 2140 } \ 2141 errno = EINVAL; \ 2142 return -1; 2143 2144int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid) 2145{ 2146 get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid); 2147} 2148 2149int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid) 2150{ 2151 get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid); 2152} 2153 2154int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState) 2155{ 2156 get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32); 2157} 2158 2159int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail) 2160{ 2161 get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8); 2162} 2163 2164int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo) 2165{ 2166 get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32); 2167} 2168 2169int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState) 2170{ 2171 get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32); 2172} 2173 2174/* 2175 * NOTE that none of the setXXX() functions below will 2176 * actually update the SDP server, unless the 2177 * {register, update}sdp_record_t() function is invoked. 2178 */ 2179 2180int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, 2181 const void *value) 2182{ 2183 sdp_data_t *d = sdp_data_alloc(dtd, value); 2184 if (d) { 2185 sdp_attr_replace(rec, attr, d); 2186 return 0; 2187 } 2188 return -1; 2189} 2190 2191static int sdp_attr_add_new_with_length(sdp_record_t *rec, 2192 uint16_t attr, uint8_t dtd, const void *value, uint32_t len) 2193{ 2194 sdp_data_t *d; 2195 2196 d = sdp_data_alloc_with_length(dtd, value, len); 2197 if (!d) 2198 return -1; 2199 2200 sdp_attr_replace(rec, attr, d); 2201 2202 return 0; 2203} 2204 2205/* 2206 * Set the information attributes of the service 2207 * pointed to by rec. The attributes are 2208 * service name, description and provider name 2209 */ 2210void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, 2211 const char *desc) 2212{ 2213 if (name) 2214 sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY, SDP_TEXT_STR8, 2215 (void *)name); 2216 if (prov) 2217 sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY, SDP_TEXT_STR8, 2218 (void *)prov); 2219 if (desc) 2220 sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY, SDP_TEXT_STR8, 2221 (void *)desc); 2222} 2223 2224static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto) 2225{ 2226 sdp_data_t *seq = NULL; 2227 void *dtds[10], *values[10]; 2228 void **seqDTDs, **seqs; 2229 int i, seqlen; 2230 sdp_list_t *p; 2231 2232 seqlen = sdp_list_len(proto); 2233 seqDTDs = (void **)malloc(seqlen * sizeof(void *)); 2234 seqs = (void **)malloc(seqlen * sizeof(void *)); 2235 for (i = 0, p = proto; p; p = p->next, i++) { 2236 sdp_list_t *elt = (sdp_list_t *)p->data; 2237 sdp_data_t *s; 2238 uuid_t *uuid = NULL; 2239 unsigned int pslen = 0; 2240 for (; elt && pslen < ARRAY_SIZE(dtds); elt = elt->next, pslen++) { 2241 sdp_data_t *d = (sdp_data_t *)elt->data; 2242 dtds[pslen] = &d->dtd; 2243 switch (d->dtd) { 2244 case SDP_UUID16: 2245 uuid = (uuid_t *) d; 2246 values[pslen] = &uuid->value.uuid16; 2247 break; 2248 case SDP_UUID32: 2249 uuid = (uuid_t *) d; 2250 values[pslen] = &uuid->value.uuid32; 2251 break; 2252 case SDP_UUID128: 2253 uuid = (uuid_t *) d; 2254 values[pslen] = &uuid->value.uuid128; 2255 break; 2256 case SDP_UINT8: 2257 values[pslen] = &d->val.uint8; 2258 break; 2259 case SDP_UINT16: 2260 values[pslen] = &d->val.uint16; 2261 break; 2262 case SDP_SEQ8: 2263 case SDP_SEQ16: 2264 case SDP_SEQ32: 2265 values[pslen] = d; 2266 break; 2267 /* FIXME: more */ 2268 } 2269 } 2270 s = sdp_seq_alloc(dtds, values, pslen); 2271 if (s) { 2272 seqDTDs[i] = &s->dtd; 2273 seqs[i] = s; 2274 if (uuid) 2275 sdp_pattern_add_uuid(rec, uuid); 2276 } 2277 } 2278 seq = sdp_seq_alloc(seqDTDs, seqs, seqlen); 2279 free(seqDTDs); 2280 free(seqs); 2281 return seq; 2282} 2283 2284/* 2285 * sets the access protocols of the service specified 2286 * to the value specified in "access_proto" 2287 * 2288 * Note that if there are alternate mechanisms by 2289 * which the service is accessed, then they should 2290 * be specified as sequences 2291 * 2292 * Using a value of NULL for accessProtocols has 2293 * effect of removing this attribute (if previously set) 2294 * 2295 * This function replaces the existing sdp_access_proto_t 2296 * structure (if any) with the new one specified. 2297 * 2298 * returns 0 if successful or -1 if there is a failure. 2299 */ 2300int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *ap) 2301{ 2302 const sdp_list_t *p; 2303 sdp_data_t *protos = NULL; 2304 2305 for (p = ap; p; p = p->next) { 2306 sdp_data_t *seq = access_proto_to_dataseq(rec, 2307 (sdp_list_t *) p->data); 2308 protos = sdp_seq_append(protos, seq); 2309 } 2310 2311 sdp_attr_add(rec, SDP_ATTR_PROTO_DESC_LIST, protos); 2312 2313 return 0; 2314} 2315 2316int sdp_set_add_access_protos(sdp_record_t *rec, const sdp_list_t *ap) 2317{ 2318 const sdp_list_t *p; 2319 sdp_data_t *protos = NULL; 2320 2321 for (p = ap; p; p = p->next) { 2322 sdp_data_t *seq = access_proto_to_dataseq(rec, 2323 (sdp_list_t *) p->data); 2324 protos = sdp_seq_append(protos, seq); 2325 } 2326 2327 sdp_attr_add(rec, SDP_ATTR_ADD_PROTO_DESC_LIST, 2328 protos ? sdp_data_alloc(SDP_SEQ8, protos) : NULL); 2329 2330 return 0; 2331} 2332 2333/* 2334 * set the "LanguageBase" attributes of the service record 2335 * record to the value specified in "langAttrList". 2336 * 2337 * "langAttrList" is a linked list of "sdp_lang_attr_t" 2338 * objects, one for each language in which user visible 2339 * attributes are present in the service record. 2340 * 2341 * Using a value of NULL for langAttrList has 2342 * effect of removing this attribute (if previously set) 2343 * 2344 * This function replaces the exisiting sdp_lang_attr_t 2345 * structure (if any) with the new one specified. 2346 * 2347 * returns 0 if successful or -1 if there is a failure. 2348 */ 2349int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *seq) 2350{ 2351 uint8_t uint16 = SDP_UINT16; 2352 int status = 0, i = 0, seqlen = sdp_list_len(seq); 2353 void **dtds = (void **)malloc(3 * seqlen * sizeof(void *)); 2354 void **values = (void **)malloc(3 * seqlen * sizeof(void *)); 2355 const sdp_list_t *p; 2356 2357 for (p = seq; p; p = p->next) { 2358 sdp_lang_attr_t *lang = (sdp_lang_attr_t *)p->data; 2359 if (!lang) { 2360 status = -1; 2361 break; 2362 } 2363 dtds[i] = &uint16; 2364 values[i] = &lang->code_ISO639; 2365 i++; 2366 dtds[i] = &uint16; 2367 values[i] = &lang->encoding; 2368 i++; 2369 dtds[i] = &uint16; 2370 values[i] = &lang->base_offset; 2371 i++; 2372 } 2373 if (status == 0) { 2374 sdp_data_t *seq = sdp_seq_alloc(dtds, values, 3 * seqlen); 2375 sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, seq); 2376 } 2377 free(dtds); 2378 free(values); 2379 return status; 2380} 2381 2382/* 2383 * set the "ServiceID" attribute of the service. 2384 * 2385 * This is the UUID of the service. 2386 * 2387 * returns 0 if successful or -1 if there is a failure. 2388 */ 2389void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid) 2390{ 2391 switch (uuid.type) { 2392 case SDP_UUID16: 2393 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID16, 2394 &uuid.value.uuid16); 2395 break; 2396 case SDP_UUID32: 2397 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID32, 2398 &uuid.value.uuid32); 2399 break; 2400 case SDP_UUID128: 2401 sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID128, 2402 &uuid.value.uuid128); 2403 break; 2404 } 2405 sdp_pattern_add_uuid(rec, &uuid); 2406} 2407 2408/* 2409 * set the GroupID attribute of the service record defining a group. 2410 * 2411 * This is the UUID of the group. 2412 * 2413 * returns 0 if successful or -1 if there is a failure. 2414 */ 2415void sdp_set_group_id(sdp_record_t *rec, uuid_t uuid) 2416{ 2417 switch (uuid.type) { 2418 case SDP_UUID16: 2419 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID16, 2420 &uuid.value.uuid16); 2421 break; 2422 case SDP_UUID32: 2423 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID32, 2424 &uuid.value.uuid32); 2425 break; 2426 case SDP_UUID128: 2427 sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID128, 2428 &uuid.value.uuid128); 2429 break; 2430 } 2431 sdp_pattern_add_uuid(rec, &uuid); 2432} 2433 2434/* 2435 * set the ProfileDescriptorList attribute of the service record 2436 * pointed to by record to the value specified in "profileDesc". 2437 * 2438 * Each element in the list is an object of type 2439 * sdp_profile_desc_t which is a definition of the 2440 * Bluetooth profile that this service conforms to. 2441 * 2442 * Using a value of NULL for profileDesc has 2443 * effect of removing this attribute (if previously set) 2444 * 2445 * This function replaces the exisiting ProfileDescriptorList 2446 * structure (if any) with the new one specified. 2447 * 2448 * returns 0 if successful or -1 if there is a failure. 2449 */ 2450int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles) 2451{ 2452 int status = 0; 2453 uint8_t uuid16 = SDP_UUID16; 2454 uint8_t uuid32 = SDP_UUID32; 2455 uint8_t uuid128 = SDP_UUID128; 2456 uint8_t uint16 = SDP_UINT16; 2457 int i = 0, seqlen = sdp_list_len(profiles); 2458 void **seqDTDs = (void **)malloc(seqlen * sizeof(void *)); 2459 void **seqs = (void **)malloc(seqlen * sizeof(void *)); 2460 const sdp_list_t *p; 2461 2462 for (p = profiles; p; p = p->next) { 2463 sdp_data_t *seq; 2464 void *dtds[2], *values[2]; 2465 sdp_profile_desc_t *profile = (sdp_profile_desc_t *)p->data; 2466 if (!profile) { 2467 status = -1; 2468 break; 2469 } 2470 switch (profile->uuid.type) { 2471 case SDP_UUID16: 2472 dtds[0] = &uuid16; 2473 values[0] = &profile->uuid.value.uuid16; 2474 break; 2475 case SDP_UUID32: 2476 dtds[0] = &uuid32; 2477 values[0] = &profile->uuid.value.uuid32; 2478 break; 2479 case SDP_UUID128: 2480 dtds[0] = &uuid128; 2481 values[0] = &profile->uuid.value.uuid128; 2482 break; 2483 default: 2484 status = -1; 2485 break; 2486 } 2487 dtds[1] = &uint16; 2488 values[1] = &profile->version; 2489 seq = sdp_seq_alloc(dtds, values, 2); 2490 if (seq) { 2491 seqDTDs[i] = &seq->dtd; 2492 seqs[i] = seq; 2493 sdp_pattern_add_uuid(rec, &profile->uuid); 2494 } 2495 i++; 2496 } 2497 if (status == 0) { 2498 sdp_data_t *pAPSeq = sdp_seq_alloc(seqDTDs, seqs, seqlen); 2499 sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, pAPSeq); 2500 } 2501 free(seqDTDs); 2502 free(seqs); 2503 return status; 2504} 2505 2506/* 2507 * sets various URL attributes of the service 2508 * pointed to by record. The URL include 2509 * 2510 * client: a URL to the client's 2511 * platform specific (WinCE, PalmOS) executable 2512 * code that can be used to access this service. 2513 * 2514 * doc: a URL pointing to service documentation 2515 * 2516 * icon: a URL to an icon that can be used to represent 2517 * this service. 2518 * 2519 * Note that you need to pass NULL for any URLs 2520 * that you don't want to set or remove 2521 */ 2522void sdp_set_url_attr(sdp_record_t *rec, const char *client, const char *doc, 2523 const char *icon) 2524{ 2525 sdp_attr_add_new(rec, SDP_ATTR_CLNT_EXEC_URL, SDP_URL_STR8, client); 2526 sdp_attr_add_new(rec, SDP_ATTR_DOC_URL, SDP_URL_STR8, doc); 2527 sdp_attr_add_new(rec, SDP_ATTR_ICON_URL, SDP_URL_STR8, icon); 2528} 2529 2530uuid_t *sdp_uuid16_create(uuid_t *u, uint16_t val) 2531{ 2532 memset(u, 0, sizeof(uuid_t)); 2533 u->type = SDP_UUID16; 2534 u->value.uuid16 = val; 2535 return u; 2536} 2537 2538uuid_t *sdp_uuid32_create(uuid_t *u, uint32_t val) 2539{ 2540 memset(u, 0, sizeof(uuid_t)); 2541 u->type = SDP_UUID32; 2542 u->value.uuid32 = val; 2543 return u; 2544} 2545 2546uuid_t *sdp_uuid128_create(uuid_t *u, const void *val) 2547{ 2548 memset(u, 0, sizeof(uuid_t)); 2549 u->type = SDP_UUID128; 2550 memcpy(&u->value.uuid128, val, sizeof(uint128_t)); 2551 return u; 2552} 2553 2554/* 2555 * UUID comparison function 2556 * returns 0 if uuidValue1 == uuidValue2 else -1 2557 */ 2558int sdp_uuid_cmp(const void *p1, const void *p2) 2559{ 2560 uuid_t *u1 = sdp_uuid_to_uuid128((uuid_t *) p1); 2561 uuid_t *u2 = sdp_uuid_to_uuid128((uuid_t *) p2); 2562 int ret; 2563 2564 ret = sdp_uuid128_cmp(u1, u2); 2565 2566 bt_free(u1); 2567 bt_free(u2); 2568 2569 return ret; 2570} 2571 2572/* 2573 * UUID comparison function 2574 * returns 0 if uuidValue1 == uuidValue2 else -1 2575 */ 2576int sdp_uuid16_cmp(const void *p1, const void *p2) 2577{ 2578 const uuid_t *u1 = (const uuid_t *)p1; 2579 const uuid_t *u2 = (const uuid_t *)p2; 2580 return memcmp(&u1->value.uuid16, &u2->value.uuid16, sizeof(uint16_t)); 2581} 2582 2583/* 2584 * UUID comparison function 2585 * returns 0 if uuidValue1 == uuidValue2 else -1 2586 */ 2587int sdp_uuid128_cmp(const void *p1, const void *p2) 2588{ 2589 const uuid_t *u1 = (const uuid_t *)p1; 2590 const uuid_t *u2 = (const uuid_t *)p2; 2591 return memcmp(&u1->value.uuid128, &u2->value.uuid128, sizeof(uint128_t)); 2592} 2593 2594/* 2595 * 128 to 16 bit and 32 to 16 bit UUID conversion functions 2596 * yet to be implemented. Note that the input is in NBO in 2597 * both 32 and 128 bit UUIDs and conversion is needed 2598 */ 2599void sdp_uuid16_to_uuid128(uuid_t *uuid128, uuid_t *uuid16) 2600{ 2601 /* 2602 * We have a 16 bit value, which needs to be added to 2603 * bytes 3 and 4 (at indices 2 and 3) of the Bluetooth base 2604 */ 2605 unsigned short data1; 2606 2607 /* allocate a 128bit UUID and init to the Bluetooth base UUID */ 2608 uuid128->value.uuid128 = bluetooth_base_uuid; 2609 uuid128->type = SDP_UUID128; 2610 2611 /* extract bytes 2 and 3 of 128bit BT base UUID */ 2612 memcpy(&data1, &bluetooth_base_uuid.data[2], 2); 2613 2614 /* add the given UUID (16 bits) */ 2615 data1 += htons(uuid16->value.uuid16); 2616 2617 /* set bytes 2 and 3 of the 128 bit value */ 2618 memcpy(&uuid128->value.uuid128.data[2], &data1, 2); 2619} 2620 2621void sdp_uuid32_to_uuid128(uuid_t *uuid128, uuid_t *uuid32) 2622{ 2623 /* 2624 * We have a 32 bit value, which needs to be added to 2625 * bytes 1->4 (at indices 0 thru 3) of the Bluetooth base 2626 */ 2627 unsigned int data0; 2628 2629 /* allocate a 128bit UUID and init to the Bluetooth base UUID */ 2630 uuid128->value.uuid128 = bluetooth_base_uuid; 2631 uuid128->type = SDP_UUID128; 2632 2633 /* extract first 4 bytes */ 2634 memcpy(&data0, &bluetooth_base_uuid.data[0], 4); 2635 2636 /* add the given UUID (32bits) */ 2637 data0 += htonl(uuid32->value.uuid32); 2638 2639 /* set the 4 bytes of the 128 bit value */ 2640 memcpy(&uuid128->value.uuid128.data[0], &data0, 4); 2641} 2642 2643uuid_t *sdp_uuid_to_uuid128(uuid_t *uuid) 2644{ 2645 uuid_t *uuid128 = bt_malloc(sizeof(uuid_t)); 2646 memset(uuid128, 0, sizeof(uuid_t)); 2647 switch (uuid->type) { 2648 case SDP_UUID128: 2649 *uuid128 = *uuid; 2650 break; 2651 case SDP_UUID32: 2652 sdp_uuid32_to_uuid128(uuid128, uuid); 2653 break; 2654 case SDP_UUID16: 2655 sdp_uuid16_to_uuid128(uuid128, uuid); 2656 break; 2657 } 2658 return uuid128; 2659} 2660 2661/* 2662 * converts a 128-bit uuid to a 16/32-bit one if possible 2663 * returns true if uuid contains a 16/32-bit UUID at exit 2664 */ 2665int sdp_uuid128_to_uuid(uuid_t *uuid) 2666{ 2667 uint128_t *b = &bluetooth_base_uuid; 2668 uint128_t *u = &uuid->value.uuid128; 2669 uint32_t data; 2670 unsigned int i; 2671 2672 if (uuid->type != SDP_UUID128) 2673 return 1; 2674 2675 for (i = 4; i < sizeof(b->data); i++) 2676 if (b->data[i] != u->data[i]) 2677 return 0; 2678 2679 memcpy(&data, u->data, 4); 2680 data = htonl(data); 2681 if (data <= 0xffff) { 2682 uuid->type = SDP_UUID16; 2683 uuid->value.uuid16 = (uint16_t) data; 2684 } else { 2685 uuid->type = SDP_UUID32; 2686 uuid->value.uuid32 = data; 2687 } 2688 return 1; 2689} 2690 2691/* 2692 * convert a UUID to the 16-bit short-form 2693 */ 2694int sdp_uuid_to_proto(uuid_t *uuid) 2695{ 2696 uuid_t u = *uuid; 2697 if (sdp_uuid128_to_uuid(&u)) { 2698 switch (u.type) { 2699 case SDP_UUID16: 2700 return u.value.uuid16; 2701 case SDP_UUID32: 2702 return u.value.uuid32; 2703 } 2704 } 2705 return 0; 2706} 2707 2708/* 2709 * This function appends data to the PDU buffer "dst" from source "src". 2710 * The data length is also computed and set. 2711 * Should the PDU length exceed 2^8, then sequence type is 2712 * set accordingly and the data is memmove()'d. 2713 */ 2714void sdp_append_to_buf(sdp_buf_t *dst, uint8_t *data, uint32_t len) 2715{ 2716 uint8_t *p = dst->data; 2717 uint8_t dtd = *(uint8_t *) p; 2718 2719 SDPDBG("Append src size: %d\n", len); 2720 SDPDBG("Append dst size: %d\n", dst->data_size); 2721 SDPDBG("Dst buffer size: %d\n", dst->buf_size); 2722 if (dst->data_size == 0 && dtd == 0) { 2723 /* create initial sequence */ 2724 *(uint8_t *)p = SDP_SEQ8; 2725 p += sizeof(uint8_t); 2726 dst->data_size += sizeof(uint8_t); 2727 /* reserve space for sequence size */ 2728 p += sizeof(uint8_t); 2729 dst->data_size += sizeof(uint8_t); 2730 } 2731 2732 memcpy(dst->data + dst->data_size, data, len); 2733 dst->data_size += len; 2734 2735 dtd = *(uint8_t *)dst->data; 2736 if (dst->data_size > UCHAR_MAX && dtd == SDP_SEQ8) { 2737 short offset = sizeof(uint8_t) + sizeof(uint8_t); 2738 memmove(dst->data + offset + 1, dst->data + offset, 2739 dst->data_size - offset); 2740 p = dst->data; 2741 *(uint8_t *) p = SDP_SEQ16; 2742 p += sizeof(uint8_t); 2743 dst->data_size += 1; 2744 } 2745 p = dst->data; 2746 dtd = *(uint8_t *) p; 2747 p += sizeof(uint8_t); 2748 switch (dtd) { 2749 case SDP_SEQ8: 2750 *(uint8_t *) p = dst->data_size - sizeof(uint8_t) - sizeof(uint8_t); 2751 break; 2752 case SDP_SEQ16: 2753 bt_put_unaligned(htons(dst->data_size - sizeof(uint8_t) - sizeof(uint16_t)), (uint16_t *) p); 2754 break; 2755 case SDP_SEQ32: 2756 bt_put_unaligned(htonl(dst->data_size - sizeof(uint8_t) - sizeof(uint32_t)), (uint32_t *) p); 2757 break; 2758 } 2759} 2760 2761void sdp_append_to_pdu(sdp_buf_t *pdu, sdp_data_t *d) 2762{ 2763 sdp_buf_t append; 2764 2765 memset(&append, 0, sizeof(sdp_buf_t)); 2766 sdp_gen_buffer(&append, d); 2767 append.data = malloc(append.buf_size); 2768 if (!append.data) 2769 return; 2770 2771 sdp_set_attrid(&append, d->attrId); 2772 sdp_gen_pdu(&append, d); 2773 sdp_append_to_buf(pdu, append.data, append.data_size); 2774 free(append.data); 2775} 2776 2777/* 2778 * Registers an sdp record. 2779 * 2780 * It is incorrect to call this method on a record that 2781 * has been already registered with the server. 2782 * 2783 * Returns zero on success, otherwise -1 (and sets errno). 2784 */ 2785int sdp_device_record_register_binary(sdp_session_t *session, bdaddr_t *device, uint8_t *data, uint32_t size, uint8_t flags, uint32_t *handle) 2786{ 2787 uint8_t *req, *rsp, *p; 2788 uint32_t reqsize, rspsize; 2789 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2790 int status; 2791 2792 SDPDBG(""); 2793 2794 if (!session->local) { 2795 errno = EREMOTE; 2796 return -1; 2797 } 2798 req = malloc(SDP_REQ_BUFFER_SIZE); 2799 rsp = malloc(SDP_RSP_BUFFER_SIZE); 2800 if (req == NULL || rsp == NULL) { 2801 status = -1; 2802 errno = ENOMEM; 2803 goto end; 2804 } 2805 2806 reqhdr = (sdp_pdu_hdr_t *)req; 2807 reqhdr->pdu_id = SDP_SVC_REGISTER_REQ; 2808 reqhdr->tid = htons(sdp_gen_tid(session)); 2809 reqsize = sizeof(sdp_pdu_hdr_t) + 1; 2810 p = req + sizeof(sdp_pdu_hdr_t); 2811 2812 if (bacmp(device, BDADDR_ANY)) { 2813 *p++ = flags | SDP_DEVICE_RECORD; 2814 bacpy((bdaddr_t *) p, device); 2815 p += sizeof(bdaddr_t); 2816 reqsize += sizeof(bdaddr_t); 2817 } else 2818 *p++ = flags; 2819 2820 memcpy(p, data, size); 2821 reqsize += size; 2822 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2823 2824 status = sdp_send_req_w4_rsp(session, req, rsp, reqsize, &rspsize); 2825 if (status < 0) 2826 goto end; 2827 2828 if (rspsize < sizeof(sdp_pdu_hdr_t)) { 2829 SDPERR("Unexpected end of packet"); 2830 errno = EPROTO; 2831 status = -1; 2832 goto end; 2833 } 2834 2835 rsphdr = (sdp_pdu_hdr_t *) rsp; 2836 p = rsp + sizeof(sdp_pdu_hdr_t); 2837 2838 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 2839 /* Invalid service record */ 2840 errno = EINVAL; 2841 status = -1; 2842 } else if (rsphdr->pdu_id != SDP_SVC_REGISTER_RSP) { 2843 errno = EPROTO; 2844 status = -1; 2845 } else { 2846 if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint32_t)) { 2847 SDPERR("Unexpected end of packet"); 2848 errno = EPROTO; 2849 status = -1; 2850 goto end; 2851 } 2852 if (handle) 2853 *handle = ntohl(bt_get_unaligned((uint32_t *) p)); 2854 } 2855 2856end: 2857 if (req) 2858 free(req); 2859 2860 if (rsp) 2861 free(rsp); 2862 2863 return status; 2864} 2865 2866int sdp_device_record_register(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec, uint8_t flags) 2867{ 2868 sdp_buf_t pdu; 2869 uint32_t handle; 2870 int err; 2871 2872 SDPDBG(""); 2873 2874 if (rec->handle && rec->handle != 0xffffffff) { 2875 uint32_t handle = rec->handle; 2876 sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle); 2877 sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data); 2878 } 2879 2880 if (sdp_gen_record_pdu(rec, &pdu) < 0) { 2881 errno = ENOMEM; 2882 return -1; 2883 } 2884 2885 err = sdp_device_record_register_binary(session, device, 2886 pdu.data, pdu.data_size, flags, &handle); 2887 2888 free(pdu.data); 2889 2890 if (err == 0) { 2891 sdp_data_t *data = sdp_data_alloc(SDP_UINT32, &handle); 2892 rec->handle = handle; 2893 sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data); 2894 } 2895 2896 return err; 2897} 2898 2899int sdp_record_register(sdp_session_t *session, sdp_record_t *rec, uint8_t flags) 2900{ 2901 return sdp_device_record_register(session, BDADDR_ANY, rec, flags); 2902} 2903 2904/* 2905 * unregister a service record 2906 */ 2907int sdp_device_record_unregister_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle) 2908{ 2909 uint8_t *reqbuf, *rspbuf, *p; 2910 uint32_t reqsize = 0, rspsize = 0; 2911 sdp_pdu_hdr_t *reqhdr, *rsphdr; 2912 int status; 2913 2914 SDPDBG(""); 2915 2916 if (handle == SDP_SERVER_RECORD_HANDLE) { 2917 errno = EINVAL; 2918 return -1; 2919 } 2920 2921 if (!session->local) { 2922 errno = EREMOTE; 2923 return -1; 2924 } 2925 2926 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 2927 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 2928 if (!reqbuf || !rspbuf) { 2929 errno = ENOMEM; 2930 status = -1; 2931 goto end; 2932 } 2933 reqhdr = (sdp_pdu_hdr_t *) reqbuf; 2934 reqhdr->pdu_id = SDP_SVC_REMOVE_REQ; 2935 reqhdr->tid = htons(sdp_gen_tid(session)); 2936 2937 p = reqbuf + sizeof(sdp_pdu_hdr_t); 2938 reqsize = sizeof(sdp_pdu_hdr_t); 2939 bt_put_unaligned(htonl(handle), (uint32_t *) p); 2940 reqsize += sizeof(uint32_t); 2941 2942 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 2943 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 2944 if (status < 0) 2945 goto end; 2946 2947 if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) { 2948 SDPERR("Unexpected end of packet"); 2949 errno = EPROTO; 2950 status = -1; 2951 goto end; 2952 } 2953 2954 rsphdr = (sdp_pdu_hdr_t *) rspbuf; 2955 p = rspbuf + sizeof(sdp_pdu_hdr_t); 2956 status = bt_get_unaligned((uint16_t *) p); 2957 2958 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 2959 /* For this case the status always is invalid record handle */ 2960 errno = EINVAL; 2961 status = -1; 2962 } else if (rsphdr->pdu_id != SDP_SVC_REMOVE_RSP) { 2963 errno = EPROTO; 2964 status = -1; 2965 } 2966end: 2967 if (reqbuf) 2968 free(reqbuf); 2969 2970 if (rspbuf) 2971 free(rspbuf); 2972 2973 return status; 2974} 2975 2976int sdp_device_record_unregister(sdp_session_t *session, bdaddr_t *device, sdp_record_t *rec) 2977{ 2978 int err; 2979 2980 err = sdp_device_record_unregister_binary(session, device, rec->handle); 2981 if (err == 0) 2982 sdp_record_free(rec); 2983 2984 return err; 2985} 2986 2987int sdp_record_unregister(sdp_session_t *session, sdp_record_t *rec) 2988{ 2989 return sdp_device_record_unregister(session, BDADDR_ANY, rec); 2990} 2991 2992/* 2993 * modify an existing service record 2994 */ 2995int sdp_device_record_update_binary(sdp_session_t *session, bdaddr_t *device, uint32_t handle, uint8_t *data, uint32_t size) 2996{ 2997 return -1; 2998} 2999 3000int sdp_device_record_update(sdp_session_t *session, bdaddr_t *device, const sdp_record_t *rec) 3001{ 3002 uint8_t *reqbuf, *rspbuf, *p; 3003 uint32_t reqsize, rspsize; 3004 sdp_pdu_hdr_t *reqhdr, *rsphdr; 3005 uint32_t handle; 3006 sdp_buf_t pdu; 3007 int status; 3008 3009 SDPDBG(""); 3010 3011 handle = rec->handle; 3012 3013 if (handle == SDP_SERVER_RECORD_HANDLE) { 3014 errno = EINVAL; 3015 return -1; 3016 } 3017 if (!session->local) { 3018 errno = EREMOTE; 3019 return -1; 3020 } 3021 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3022 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 3023 if (!reqbuf || !rspbuf) { 3024 errno = ENOMEM; 3025 status = -1; 3026 goto end; 3027 } 3028 reqhdr = (sdp_pdu_hdr_t *) reqbuf; 3029 reqhdr->pdu_id = SDP_SVC_UPDATE_REQ; 3030 reqhdr->tid = htons(sdp_gen_tid(session)); 3031 3032 p = reqbuf + sizeof(sdp_pdu_hdr_t); 3033 reqsize = sizeof(sdp_pdu_hdr_t); 3034 3035 bt_put_unaligned(htonl(handle), (uint32_t *) p); 3036 reqsize += sizeof(uint32_t); 3037 p += sizeof(uint32_t); 3038 3039 if (sdp_gen_record_pdu(rec, &pdu) < 0) { 3040 errno = ENOMEM; 3041 status = -1; 3042 goto end; 3043 } 3044 memcpy(p, pdu.data, pdu.data_size); 3045 reqsize += pdu.data_size; 3046 free(pdu.data); 3047 3048 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 3049 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 3050 if (status < 0) 3051 goto end; 3052 3053 if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) { 3054 SDPERR("Unexpected end of packet"); 3055 errno = EPROTO; 3056 status = -1; 3057 goto end; 3058 } 3059 3060 SDPDBG("Send req status : %d\n", status); 3061 3062 rsphdr = (sdp_pdu_hdr_t *) rspbuf; 3063 p = rspbuf + sizeof(sdp_pdu_hdr_t); 3064 status = bt_get_unaligned((uint16_t *) p); 3065 3066 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 3067 /* The status can be invalid sintax or invalid record handle */ 3068 errno = EINVAL; 3069 status = -1; 3070 } else if (rsphdr->pdu_id != SDP_SVC_UPDATE_RSP) { 3071 errno = EPROTO; 3072 status = -1; 3073 } 3074end: 3075 if (reqbuf) 3076 free(reqbuf); 3077 if (rspbuf) 3078 free(rspbuf); 3079 return status; 3080} 3081 3082int sdp_record_update(sdp_session_t *session, const sdp_record_t *rec) 3083{ 3084 return sdp_device_record_update(session, BDADDR_ANY, rec); 3085} 3086 3087sdp_record_t *sdp_record_alloc() 3088{ 3089 sdp_record_t *rec = malloc(sizeof(sdp_record_t)); 3090 memset((void *)rec, 0, sizeof(sdp_record_t)); 3091 rec->handle = 0xffffffff; 3092 return rec; 3093} 3094 3095/* 3096 * Free the contents of a service record 3097 */ 3098void sdp_record_free(sdp_record_t *rec) 3099{ 3100 sdp_list_free(rec->attrlist, (sdp_free_func_t)sdp_data_free); 3101 sdp_list_free(rec->pattern, free); 3102 free(rec); 3103} 3104 3105void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid) 3106{ 3107 uuid_t *uuid128 = sdp_uuid_to_uuid128(uuid); 3108 3109 SDPDBG("SvcRec : 0x%lx\n", (unsigned long)rec); 3110 SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); 3111 SDPDBG("Trying to add : 0x%lx\n", (unsigned long)uuid128); 3112 3113 if (sdp_list_find(rec->pattern, uuid128, sdp_uuid128_cmp) == NULL) 3114 rec->pattern = sdp_list_insert_sorted(rec->pattern, uuid128, sdp_uuid128_cmp); 3115 else 3116 bt_free(uuid128); 3117 3118 SDPDBG("Elements in target pattern : %d\n", sdp_list_len(rec->pattern)); 3119} 3120 3121void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq) 3122{ 3123 for (; seq; seq = seq->next) { 3124 uuid_t *uuid = (uuid_t *)seq->data; 3125 sdp_pattern_add_uuid(rec, uuid); 3126 } 3127} 3128 3129/* 3130 * Extract a sequence of service record handles from a PDU buffer 3131 * and add the entries to a sdp_list_t. Note that the service record 3132 * handles are not in "data element sequence" form, but just like 3133 * an array of service handles 3134 */ 3135static void extract_record_handle_seq(uint8_t *pdu, int bufsize, sdp_list_t **seq, int count, unsigned int *scanned) 3136{ 3137 sdp_list_t *pSeq = *seq; 3138 uint8_t *pdata = pdu; 3139 int n; 3140 3141 for (n = 0; n < count; n++) { 3142 uint32_t *pSvcRec; 3143 if (bufsize < (int) sizeof(uint32_t)) { 3144 SDPERR("Unexpected end of packet"); 3145 break; 3146 } 3147 pSvcRec = malloc(sizeof(uint32_t)); 3148 if (!pSvcRec) 3149 break; 3150 *pSvcRec = ntohl(bt_get_unaligned((uint32_t *) pdata)); 3151 pSeq = sdp_list_append(pSeq, pSvcRec); 3152 pdata += sizeof(uint32_t); 3153 *scanned += sizeof(uint32_t); 3154 bufsize -= sizeof(uint32_t); 3155 } 3156 *seq = pSeq; 3157} 3158/* 3159 * Generate the attribute sequence pdu form 3160 * from sdp_list_t elements. Return length of attr seq 3161 */ 3162static int gen_dataseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dtd) 3163{ 3164 sdp_data_t *dataseq; 3165 void **types, **values; 3166 sdp_buf_t buf; 3167 int i, seqlen = sdp_list_len(seq); 3168 3169 // Fill up the value and the dtd arrays 3170 SDPDBG(""); 3171 3172 SDPDBG("Seq length : %d\n", seqlen); 3173 3174 types = malloc(seqlen * sizeof(void *)); 3175 if (!types) 3176 return -ENOMEM; 3177 3178 values = malloc(seqlen * sizeof(void *)); 3179 if (!values) { 3180 free(types); 3181 return -ENOMEM; 3182 } 3183 3184 for (i = 0; i < seqlen; i++) { 3185 void *data = seq->data; 3186 types[i] = &dtd; 3187 if (SDP_IS_UUID(dtd)) 3188 data = &((uuid_t *)data)->value; 3189 values[i] = data; 3190 seq = seq->next; 3191 } 3192 3193 dataseq = sdp_seq_alloc(types, values, seqlen); 3194 if (!dataseq) { 3195 free(types); 3196 free(values); 3197 return -ENOMEM; 3198 } 3199 3200 memset(&buf, 0, sizeof(sdp_buf_t)); 3201 sdp_gen_buffer(&buf, dataseq); 3202 buf.data = malloc(buf.buf_size); 3203 3204 if (!buf.data) { 3205 sdp_data_free(dataseq); 3206 free(types); 3207 free(values); 3208 return -ENOMEM; 3209 } 3210 3211 SDPDBG("Data Seq : 0x%p\n", seq); 3212 seqlen = sdp_gen_pdu(&buf, dataseq); 3213 SDPDBG("Copying : %d\n", buf.data_size); 3214 memcpy(dst, buf.data, buf.data_size); 3215 3216 sdp_data_free(dataseq); 3217 3218 free(types); 3219 free(values); 3220 free(buf.data); 3221 return seqlen; 3222} 3223 3224static int gen_searchseq_pdu(uint8_t *dst, const sdp_list_t *seq) 3225{ 3226 uuid_t *uuid = (uuid_t *) seq->data; 3227 return gen_dataseq_pdu(dst, seq, uuid->type); 3228} 3229 3230static int gen_attridseq_pdu(uint8_t *dst, const sdp_list_t *seq, uint8_t dataType) 3231{ 3232 return gen_dataseq_pdu(dst, seq, dataType); 3233} 3234 3235typedef struct { 3236 uint8_t length; 3237 unsigned char data[16]; 3238} __attribute__ ((packed)) sdp_cstate_t; 3239 3240static int copy_cstate(uint8_t *pdata, int pdata_len, const sdp_cstate_t *cstate) 3241{ 3242 if (cstate) { 3243 uint8_t len = cstate->length; 3244 if (len >= pdata_len) { 3245 SDPERR("Continuation state size exceeds internal buffer"); 3246 len = pdata_len - 1; 3247 } 3248 *pdata++ = len; 3249 memcpy(pdata, cstate->data, len); 3250 return len + 1; 3251 } 3252 *pdata = 0; 3253 return 1; 3254} 3255 3256/* 3257 * This is a service search request. 3258 * 3259 * INPUT : 3260 * 3261 * sdp_list_t *search 3262 * Singly linked list containing elements of the search 3263 * pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16) 3264 * of the service to be searched 3265 * 3266 * uint16_t max_rec_num 3267 * A 16 bit integer which tells the service, the maximum 3268 * entries that the client can handle in the response. The 3269 * server is obliged not to return > max_rec_num entries 3270 * 3271 * OUTPUT : 3272 * 3273 * int return value 3274 * 0: 3275 * The request completed successfully. This does not 3276 * mean the requested services were found 3277 * -1: 3278 * On any failure and sets errno 3279 * 3280 * sdp_list_t **rsp_list 3281 * This variable is set on a successful return if there are 3282 * non-zero service handles. It is a singly linked list of 3283 * service record handles (uint16_t) 3284 */ 3285int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search, 3286 uint16_t max_rec_num, sdp_list_t **rsp) 3287{ 3288 int status = 0; 3289 uint32_t reqsize = 0, _reqsize; 3290 uint32_t rspsize = 0, rsplen; 3291 int seqlen = 0; 3292 int total_rec_count, rec_count; 3293 unsigned scanned, pdata_len; 3294 uint8_t *pdata, *_pdata; 3295 uint8_t *reqbuf, *rspbuf; 3296 sdp_pdu_hdr_t *reqhdr, *rsphdr; 3297 sdp_cstate_t *cstate = NULL; 3298 3299 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3300 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 3301 if (!reqbuf || !rspbuf) { 3302 errno = ENOMEM; 3303 status = -1; 3304 goto end; 3305 } 3306 reqhdr = (sdp_pdu_hdr_t *) reqbuf; 3307 reqhdr->pdu_id = SDP_SVC_SEARCH_REQ; 3308 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 3309 reqsize = sizeof(sdp_pdu_hdr_t); 3310 3311 // add service class IDs for search 3312 seqlen = gen_searchseq_pdu(pdata, search); 3313 3314 SDPDBG("Data seq added : %d\n", seqlen); 3315 3316 // set the length and increment the pointer 3317 reqsize += seqlen; 3318 pdata += seqlen; 3319 3320 // specify the maximum svc rec count that client expects 3321 bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata); 3322 reqsize += sizeof(uint16_t); 3323 pdata += sizeof(uint16_t); 3324 3325 _reqsize = reqsize; 3326 _pdata = pdata; 3327 *rsp = NULL; 3328 3329 do { 3330 // Add continuation state or NULL (first time) 3331 reqsize = _reqsize + copy_cstate(_pdata, 3332 SDP_REQ_BUFFER_SIZE - _reqsize, cstate); 3333 3334 // Set the request header's param length 3335 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 3336 3337 reqhdr->tid = htons(sdp_gen_tid(session)); 3338 /* 3339 * Send the request, wait for response and if 3340 * no error, set the appropriate values and return 3341 */ 3342 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 3343 if (status < 0) 3344 goto end; 3345 3346 if (rspsize < sizeof(sdp_pdu_hdr_t)) { 3347 SDPERR("Unexpected end of packet"); 3348 status = -1; 3349 goto end; 3350 } 3351 3352 rsphdr = (sdp_pdu_hdr_t *) rspbuf; 3353 rsplen = ntohs(rsphdr->plen); 3354 3355 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 3356 SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); 3357 status = -1; 3358 goto end; 3359 } 3360 scanned = 0; 3361 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 3362 pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); 3363 3364 if (pdata_len < sizeof(uint16_t) + sizeof(uint16_t)) { 3365 SDPERR("Unexpected end of packet"); 3366 status = -1; 3367 goto end; 3368 } 3369 3370 // net service record match count 3371 total_rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); 3372 pdata += sizeof(uint16_t); 3373 scanned += sizeof(uint16_t); 3374 pdata_len -= sizeof(uint16_t); 3375 rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); 3376 pdata += sizeof(uint16_t); 3377 scanned += sizeof(uint16_t); 3378 pdata_len -= sizeof(uint16_t); 3379 3380 SDPDBG("Total svc count: %d\n", total_rec_count); 3381 SDPDBG("Current svc count: %d\n", rec_count); 3382 SDPDBG("ResponseLength: %d\n", rsplen); 3383 3384 if (!rec_count) { 3385 status = -1; 3386 goto end; 3387 } 3388 extract_record_handle_seq(pdata, pdata_len, rsp, rec_count, &scanned); 3389 SDPDBG("BytesScanned : %d\n", scanned); 3390 3391 if (rsplen > scanned) { 3392 uint8_t cstate_len; 3393 3394 if (rspsize < sizeof(sdp_pdu_hdr_t) + scanned + sizeof(uint8_t)) { 3395 SDPERR("Unexpected end of packet: continuation state data missing"); 3396 status = -1; 3397 goto end; 3398 } 3399 3400 pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned; 3401 cstate_len = *(uint8_t *) pdata; 3402 if (cstate_len > 0) { 3403 cstate = (sdp_cstate_t *)pdata; 3404 SDPDBG("Cont state length: %d\n", cstate_len); 3405 } else 3406 cstate = NULL; 3407 } 3408 } while (cstate); 3409 3410end: 3411 if (reqbuf) 3412 free(reqbuf); 3413 if (rspbuf) 3414 free(rspbuf); 3415 3416 return status; 3417} 3418 3419/* 3420 * This is a service attribute request. 3421 * 3422 * INPUT : 3423 * 3424 * uint32_t handle 3425 * The handle of the service for which the attribute(s) are 3426 * requested 3427 * 3428 * sdp_attrreq_type_t reqtype 3429 * Attribute identifiers are 16 bit unsigned integers specified 3430 * in one of 2 ways described below : 3431 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 3432 * They are the actual attribute identifiers in ascending order 3433 * 3434 * SDP_ATTR_REQ_RANGE - 32bit identifier range 3435 * The high-order 16bits is the start of range 3436 * the low-order 16bits are the end of range 3437 * 0x0000 to 0xFFFF gets all attributes 3438 * 3439 * sdp_list_t *attrid 3440 * Singly linked list containing attribute identifiers desired. 3441 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 3442 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 3443 * 3444 * OUTPUT : 3445 * return sdp_record_t * 3446 * 0: 3447 * On any error and sets errno 3448 * !0: 3449 * The service record 3450 */ 3451sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, 3452 sdp_attrreq_type_t reqtype, const sdp_list_t *attrids) 3453{ 3454 uint32_t reqsize = 0, _reqsize; 3455 uint32_t rspsize = 0, rsp_count; 3456 int attr_list_len = 0; 3457 int seqlen = 0; 3458 unsigned int pdata_len; 3459 uint8_t *pdata, *_pdata; 3460 uint8_t *reqbuf, *rspbuf; 3461 sdp_pdu_hdr_t *reqhdr, *rsphdr; 3462 sdp_cstate_t *cstate = NULL; 3463 uint8_t cstate_len = 0; 3464 sdp_buf_t rsp_concat_buf; 3465 sdp_record_t *rec = 0; 3466 3467 if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) { 3468 errno = EINVAL; 3469 return 0; 3470 } 3471 3472 memset(&rsp_concat_buf, 0, sizeof(sdp_buf_t)); 3473 3474 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3475 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 3476 if (!reqbuf || !rspbuf) { 3477 errno = ENOMEM; 3478 goto end; 3479 } 3480 reqhdr = (sdp_pdu_hdr_t *) reqbuf; 3481 reqhdr->pdu_id = SDP_SVC_ATTR_REQ; 3482 3483 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 3484 reqsize = sizeof(sdp_pdu_hdr_t); 3485 3486 // add the service record handle 3487 bt_put_unaligned(htonl(handle), (uint32_t *) pdata); 3488 reqsize += sizeof(uint32_t); 3489 pdata += sizeof(uint32_t); 3490 3491 // specify the response limit 3492 bt_put_unaligned(htons(65535), (uint16_t *) pdata); 3493 reqsize += sizeof(uint16_t); 3494 pdata += sizeof(uint16_t); 3495 3496 // get attr seq PDU form 3497 seqlen = gen_attridseq_pdu(pdata, attrids, 3498 reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32); 3499 if (seqlen == -1) { 3500 errno = EINVAL; 3501 goto end; 3502 } 3503 pdata += seqlen; 3504 reqsize += seqlen; 3505 SDPDBG("Attr list length : %d\n", seqlen); 3506 3507 // save before Continuation State 3508 _pdata = pdata; 3509 _reqsize = reqsize; 3510 3511 do { 3512 int status; 3513 3514 // add NULL continuation state 3515 reqsize = _reqsize + copy_cstate(_pdata, 3516 SDP_REQ_BUFFER_SIZE - _reqsize, cstate); 3517 3518 // set the request header's param length 3519 reqhdr->tid = htons(sdp_gen_tid(session)); 3520 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 3521 3522 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 3523 if (status < 0) 3524 goto end; 3525 3526 if (rspsize < sizeof(sdp_pdu_hdr_t)) { 3527 SDPERR("Unexpected end of packet"); 3528 goto end; 3529 } 3530 3531 rsphdr = (sdp_pdu_hdr_t *) rspbuf; 3532 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 3533 SDPDBG("PDU ID : 0x%x\n", rsphdr->pdu_id); 3534 goto end; 3535 } 3536 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 3537 pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); 3538 3539 if (pdata_len < sizeof(uint16_t)) { 3540 SDPERR("Unexpected end of packet"); 3541 goto end; 3542 } 3543 3544 rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); 3545 attr_list_len += rsp_count; 3546 pdata += sizeof(uint16_t); 3547 pdata_len -= sizeof(uint16_t); 3548 3549 // if continuation state set need to re-issue request before parsing 3550 if (pdata_len < rsp_count + sizeof(uint8_t)) { 3551 SDPERR("Unexpected end of packet: continuation state data missing"); 3552 goto end; 3553 } 3554 cstate_len = *(uint8_t *) (pdata + rsp_count); 3555 3556 SDPDBG("Response id : %d\n", rsphdr->pdu_id); 3557 SDPDBG("Attrlist byte count : %d\n", rsp_count); 3558 SDPDBG("sdp_cstate_t length : %d\n", cstate_len); 3559 3560 /* 3561 * a split response: concatenate intermediate responses 3562 * and the last one (which has cstate_len == 0) 3563 */ 3564 if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { 3565 uint8_t *targetPtr = NULL; 3566 3567 cstate = cstate_len > 0 ? (sdp_cstate_t *) (pdata + rsp_count) : 0; 3568 3569 // build concatenated response buffer 3570 rsp_concat_buf.data = realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); 3571 rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; 3572 targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; 3573 memcpy(targetPtr, pdata, rsp_count); 3574 rsp_concat_buf.data_size += rsp_count; 3575 } 3576 } while (cstate); 3577 3578 if (attr_list_len > 0) { 3579 int scanned = 0; 3580 if (rsp_concat_buf.data_size != 0) { 3581 pdata = rsp_concat_buf.data; 3582 pdata_len = rsp_concat_buf.data_size; 3583 } 3584 rec = sdp_extract_pdu(pdata, pdata_len, &scanned); 3585 } 3586 3587end: 3588 if (reqbuf) 3589 free(reqbuf); 3590 if (rsp_concat_buf.data) 3591 free(rsp_concat_buf.data); 3592 if (rspbuf) 3593 free(rspbuf); 3594 return rec; 3595} 3596 3597/* 3598 * SDP transaction structure for asynchronous search 3599 */ 3600struct sdp_transaction { 3601 sdp_callback_t *cb; /* called when the transaction finishes */ 3602 void *udata; /* client user data */ 3603 uint8_t *reqbuf; /* pointer to request PDU */ 3604 sdp_buf_t rsp_concat_buf; 3605 uint32_t reqsize; /* without cstate */ 3606 int err; /* ZERO if success or the errno if failed */ 3607}; 3608 3609/* 3610 * Creates a new sdp session for asynchronous search 3611 * INPUT: 3612 * int sk 3613 * non-blocking L2CAP socket 3614 * 3615 * RETURN: 3616 * sdp_session_t * 3617 * NULL - On memory allocation failure 3618 */ 3619sdp_session_t *sdp_create(int sk, uint32_t flags) 3620{ 3621 sdp_session_t *session; 3622 struct sdp_transaction *t; 3623 3624 session = malloc(sizeof(sdp_session_t)); 3625 if (!session) { 3626 errno = ENOMEM; 3627 return NULL; 3628 } 3629 memset(session, 0, sizeof(*session)); 3630 3631 session->flags = flags; 3632 session->sock = sk; 3633 3634 t = malloc(sizeof(struct sdp_transaction)); 3635 if (!t) { 3636 errno = ENOMEM; 3637 free(session); 3638 return NULL; 3639 } 3640 memset(t, 0, sizeof(*t)); 3641 3642 session->priv = t; 3643 3644 return session; 3645} 3646 3647/* 3648 * Sets the callback function/user data used to notify the application 3649 * that the asynchronous transaction finished. This function must be 3650 * called before request an asynchronous search. 3651 * 3652 * INPUT: 3653 * sdp_session_t *session 3654 * Current sdp session to be handled 3655 * sdp_callback_t *cb 3656 * callback to be called when the transaction finishes 3657 * void *udata 3658 * user data passed to callback 3659 * RETURN: 3660 * 0 - Success 3661 * -1 - Failure 3662 */ 3663int sdp_set_notify(sdp_session_t *session, sdp_callback_t *func, void *udata) 3664{ 3665 struct sdp_transaction *t; 3666 3667 if (!session || !session->priv) 3668 return -1; 3669 3670 t = session->priv; 3671 t->cb = func; 3672 t->udata = udata; 3673 3674 return 0; 3675} 3676 3677/* 3678 * This function starts an asynchronous service search request. 3679 * The incomming and outgoing data are stored in the transaction structure 3680 * buffers. When there is incomming data the sdp_process function must be 3681 * called to get the data and handle the continuation state. 3682 * 3683 * INPUT : 3684 * sdp_session_t *session 3685 * Current sdp session to be handled 3686 * 3687 * sdp_list_t *search 3688 * Singly linked list containing elements of the search 3689 * pattern. Each entry in the list is a UUID (DataTypeSDP_UUID16) 3690 * of the service to be searched 3691 * 3692 * uint16_t max_rec_num 3693 * A 16 bit integer which tells the service, the maximum 3694 * entries that the client can handle in the response. The 3695 * server is obliged not to return > max_rec_num entries 3696 * 3697 * OUTPUT : 3698 * 3699 * int return value 3700 * 0 - if the request has been sent properly 3701 * -1 - On any failure and sets errno 3702 */ 3703 3704int sdp_service_search_async(sdp_session_t *session, const sdp_list_t *search, uint16_t max_rec_num) 3705{ 3706 struct sdp_transaction *t; 3707 sdp_pdu_hdr_t *reqhdr; 3708 uint8_t *pdata; 3709 int cstate_len, seqlen = 0; 3710 3711 if (!session || !session->priv) 3712 return -1; 3713 3714 t = session->priv; 3715 3716 /* check if the buffer is already allocated */ 3717 if (t->rsp_concat_buf.data) 3718 free(t->rsp_concat_buf.data); 3719 memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t)); 3720 3721 if (!t->reqbuf) { 3722 t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3723 if (!t->reqbuf) { 3724 t->err = ENOMEM; 3725 goto end; 3726 } 3727 } 3728 memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE); 3729 3730 reqhdr = (sdp_pdu_hdr_t *) t->reqbuf; 3731 reqhdr->tid = htons(sdp_gen_tid(session)); 3732 reqhdr->pdu_id = SDP_SVC_SEARCH_REQ; 3733 3734 // generate PDU 3735 pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t); 3736 t->reqsize = sizeof(sdp_pdu_hdr_t); 3737 3738 // add service class IDs for search 3739 seqlen = gen_searchseq_pdu(pdata, search); 3740 3741 SDPDBG("Data seq added : %d\n", seqlen); 3742 3743 // now set the length and increment the pointer 3744 t->reqsize += seqlen; 3745 pdata += seqlen; 3746 3747 bt_put_unaligned(htons(max_rec_num), (uint16_t *) pdata); 3748 t->reqsize += sizeof(uint16_t); 3749 pdata += sizeof(uint16_t); 3750 3751 // set the request header's param length 3752 cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); 3753 reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); 3754 3755 if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { 3756 SDPERR("Error sendind data:%s", strerror(errno)); 3757 t->err = errno; 3758 goto end; 3759 } 3760 3761 return 0; 3762end: 3763 3764 if (t->reqbuf) { 3765 free(t->reqbuf); 3766 t->reqbuf = NULL; 3767 } 3768 3769 return -1; 3770} 3771 3772/* 3773 * This function starts an asynchronous service attribute request. 3774 * The incomming and outgoing data are stored in the transaction structure 3775 * buffers. When there is incomming data the sdp_process function must be 3776 * called to get the data and handle the continuation state. 3777 * 3778 * INPUT : 3779 * sdp_session_t *session 3780 * Current sdp session to be handled 3781 * 3782 * uint32_t handle 3783 * The handle of the service for which the attribute(s) are 3784 * requested 3785 * 3786 * sdp_attrreq_type_t reqtype 3787 * Attribute identifiers are 16 bit unsigned integers specified 3788 * in one of 2 ways described below : 3789 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 3790 * They are the actual attribute identifiers in ascending order 3791 * 3792 * SDP_ATTR_REQ_RANGE - 32bit identifier range 3793 * The high-order 16bits is the start of range 3794 * the low-order 16bits are the end of range 3795 * 0x0000 to 0xFFFF gets all attributes 3796 * 3797 * sdp_list_t *attrid_list 3798 * Singly linked list containing attribute identifiers desired. 3799 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 3800 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 3801 * 3802 * OUTPUT : 3803 * int return value 3804 * 0 - if the request has been sent properly 3805 * -1 - On any failure and sets errno 3806 */ 3807 3808int sdp_service_attr_async(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list) 3809{ 3810 struct sdp_transaction *t; 3811 sdp_pdu_hdr_t *reqhdr; 3812 uint8_t *pdata; 3813 int cstate_len, seqlen = 0; 3814 3815 if (!session || !session->priv) 3816 return -1; 3817 3818 t = session->priv; 3819 3820 /* check if the buffer is already allocated */ 3821 if (t->rsp_concat_buf.data) 3822 free(t->rsp_concat_buf.data); 3823 memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t)); 3824 3825 if (!t->reqbuf) { 3826 t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3827 if (!t->reqbuf) { 3828 t->err = ENOMEM; 3829 goto end; 3830 } 3831 } 3832 memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE); 3833 3834 reqhdr = (sdp_pdu_hdr_t *) t->reqbuf; 3835 reqhdr->tid = htons(sdp_gen_tid(session)); 3836 reqhdr->pdu_id = SDP_SVC_ATTR_REQ; 3837 3838 // generate PDU 3839 pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t); 3840 t->reqsize = sizeof(sdp_pdu_hdr_t); 3841 3842 // add the service record handle 3843 bt_put_unaligned(htonl(handle), (uint32_t *) pdata); 3844 t->reqsize += sizeof(uint32_t); 3845 pdata += sizeof(uint32_t); 3846 3847 // specify the response limit 3848 bt_put_unaligned(htons(65535), (uint16_t *) pdata); 3849 t->reqsize += sizeof(uint16_t); 3850 pdata += sizeof(uint16_t); 3851 3852 // get attr seq PDU form 3853 seqlen = gen_attridseq_pdu(pdata, attrid_list, 3854 reqtype == SDP_ATTR_REQ_INDIVIDUAL? SDP_UINT16 : SDP_UINT32); 3855 if (seqlen == -1) { 3856 t->err = EINVAL; 3857 goto end; 3858 } 3859 3860 // now set the length and increment the pointer 3861 t->reqsize += seqlen; 3862 pdata += seqlen; 3863 SDPDBG("Attr list length : %d\n", seqlen); 3864 3865 // set the request header's param length 3866 cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); 3867 reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); 3868 3869 if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { 3870 SDPERR("Error sendind data:%s", strerror(errno)); 3871 t->err = errno; 3872 goto end; 3873 } 3874 3875 return 0; 3876end: 3877 3878 if (t->reqbuf) { 3879 free(t->reqbuf); 3880 t->reqbuf = NULL; 3881 } 3882 3883 return -1; 3884} 3885 3886/* 3887 * This function starts an asynchronous service search attributes. 3888 * It is a service search request combined with attribute request. The incomming 3889 * and outgoing data are stored in the transaction structure buffers. When there 3890 * is incomming data the sdp_process function must be called to get the data 3891 * and handle the continuation state. 3892 * 3893 * INPUT: 3894 * sdp_session_t *session 3895 * Current sdp session to be handled 3896 * 3897 * sdp_list_t *search 3898 * Singly linked list containing elements of the search 3899 * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16) 3900 * of the service to be searched 3901 * 3902 * AttributeSpecification attrSpec 3903 * Attribute identifiers are 16 bit unsigned integers specified 3904 * in one of 2 ways described below : 3905 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 3906 * They are the actual attribute identifiers in ascending order 3907 * 3908 * SDP_ATTR_REQ_RANGE - 32bit identifier range 3909 * The high-order 16bits is the start of range 3910 * the low-order 16bits are the end of range 3911 * 0x0000 to 0xFFFF gets all attributes 3912 * 3913 * sdp_list_t *attrid_list 3914 * Singly linked list containing attribute identifiers desired. 3915 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 3916 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 3917 * 3918 3919 * RETURN: 3920 * 0 - if the request has been sent properly 3921 * -1 - On any failure 3922 */ 3923int sdp_service_search_attr_async(sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list) 3924{ 3925 struct sdp_transaction *t; 3926 sdp_pdu_hdr_t *reqhdr; 3927 uint8_t *pdata; 3928 int cstate_len, seqlen = 0; 3929 3930 if (!session || !session->priv) 3931 return -1; 3932 3933 t = session->priv; 3934 3935 /* check if the buffer is already allocated */ 3936 if (t->rsp_concat_buf.data) 3937 free(t->rsp_concat_buf.data); 3938 memset(&t->rsp_concat_buf, 0, sizeof(sdp_buf_t)); 3939 3940 if (!t->reqbuf) { 3941 t->reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 3942 if (!t->reqbuf) { 3943 t->err = ENOMEM; 3944 goto end; 3945 } 3946 } 3947 memset(t->reqbuf, 0, SDP_REQ_BUFFER_SIZE); 3948 3949 reqhdr = (sdp_pdu_hdr_t *) t->reqbuf; 3950 reqhdr->tid = htons(sdp_gen_tid(session)); 3951 reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ; 3952 3953 // generate PDU 3954 pdata = t->reqbuf + sizeof(sdp_pdu_hdr_t); 3955 t->reqsize = sizeof(sdp_pdu_hdr_t); 3956 3957 // add service class IDs for search 3958 seqlen = gen_searchseq_pdu(pdata, search); 3959 3960 SDPDBG("Data seq added : %d\n", seqlen); 3961 3962 // now set the length and increment the pointer 3963 t->reqsize += seqlen; 3964 pdata += seqlen; 3965 3966 bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata); 3967 t->reqsize += sizeof(uint16_t); 3968 pdata += sizeof(uint16_t); 3969 3970 SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); 3971 3972 // get attr seq PDU form 3973 seqlen = gen_attridseq_pdu(pdata, attrid_list, 3974 reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32); 3975 if (seqlen == -1) { 3976 t->err = EINVAL; 3977 goto end; 3978 } 3979 3980 pdata += seqlen; 3981 SDPDBG("Attr list length : %d\n", seqlen); 3982 t->reqsize += seqlen; 3983 3984 // set the request header's param length 3985 cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL); 3986 reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t)); 3987 3988 if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) { 3989 SDPERR("Error sendind data:%s", strerror(errno)); 3990 t->err = errno; 3991 goto end; 3992 } 3993 3994 return 0; 3995end: 3996 3997 if (t->reqbuf) { 3998 free(t->reqbuf); 3999 t->reqbuf = NULL; 4000 } 4001 4002 return -1; 4003} 4004 4005/* 4006 * Function used to get the error reason after sdp_callback_t function has been called 4007 * and the status is 0xffff or if sdp_service_{search, attr, search_attr}_async returns -1. 4008 * It indicates that an error NOT related to SDP_ErrorResponse happened. Get errno directly 4009 * is not safe because multiple transactions can be triggered. 4010 * This function must be used with asynchronous sdp functions only. 4011 * 4012 * INPUT: 4013 * sdp_session_t *session 4014 * Current sdp session to be handled 4015 * RETURN: 4016 * 0 = No error in the current transaction 4017 * -1 - if the session is invalid 4018 * positive value - the errno value 4019 * 4020 */ 4021int sdp_get_error(sdp_session_t *session) 4022{ 4023 struct sdp_transaction *t; 4024 4025 if (!session || !session->priv) { 4026 SDPERR("Invalid session"); 4027 return -1; 4028 } 4029 4030 t = session->priv; 4031 4032 return t->err; 4033} 4034 4035/* 4036 * Receive the incomming SDP PDU. This function must be called when there is data 4037 * available to be read. On continuation state, the original request (with a new 4038 * transaction ID) and the continuation state data will be appended in the initial PDU. 4039 * If an error happens or the transaction finishes the callback function will be called. 4040 * 4041 * INPUT: 4042 * sdp_session_t *session 4043 * Current sdp session to be handled 4044 * RETURN: 4045 * 0 - if the transaction is on continuation state 4046 * -1 - On any failure or the transaction finished 4047 */ 4048int sdp_process(sdp_session_t *session) 4049{ 4050 struct sdp_transaction *t; 4051 sdp_pdu_hdr_t *reqhdr, *rsphdr; 4052 sdp_cstate_t *pcstate; 4053 uint8_t *pdata, *rspbuf, *targetPtr; 4054 int rsp_count, err = -1; 4055 size_t size = 0; 4056 int n, plen; 4057 uint16_t status = 0xffff; 4058 uint8_t pdu_id = 0x00; 4059 4060 if (!session || !session->priv) { 4061 SDPERR("Invalid session"); 4062 return -1; 4063 } 4064 4065 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 4066 if (!rspbuf) { 4067 SDPERR("Response buffer alloc failure:%s (%d)", 4068 strerror(errno), errno); 4069 return -1; 4070 } 4071 4072 memset(rspbuf, 0, SDP_RSP_BUFFER_SIZE); 4073 4074 t = session->priv; 4075 reqhdr = (sdp_pdu_hdr_t *)t->reqbuf; 4076 rsphdr = (sdp_pdu_hdr_t *)rspbuf; 4077 4078 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 4079 4080 n = sdp_read_rsp(session, rspbuf, SDP_RSP_BUFFER_SIZE); 4081 if (n < 0) { 4082 SDPERR("Read response:%s (%d)", strerror(errno), errno); 4083 t->err = errno; 4084 goto end; 4085 } 4086 4087 if (n == 0 || reqhdr->tid != rsphdr->tid || 4088 (n != (ntohs(rsphdr->plen) + (int) sizeof(sdp_pdu_hdr_t)))) { 4089 t->err = EPROTO; 4090 SDPERR("Protocol error."); 4091 goto end; 4092 } 4093 4094 pdu_id = rsphdr->pdu_id; 4095 switch (rsphdr->pdu_id) { 4096 uint8_t *ssr_pdata; 4097 uint16_t tsrc, csrc; 4098 case SDP_SVC_SEARCH_RSP: 4099 /* 4100 * TSRC: Total Service Record Count (2 bytes) 4101 * CSRC: Current Service Record Count (2 bytes) 4102 */ 4103 ssr_pdata = pdata; 4104 tsrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata)); 4105 ssr_pdata += sizeof(uint16_t); 4106 csrc = ntohs(bt_get_unaligned((uint16_t *) ssr_pdata)); 4107 4108 /* csrc should never be larger than tsrc */ 4109 if (csrc > tsrc) { 4110 t->err = EPROTO; 4111 SDPERR("Protocol error: wrong current service record count value."); 4112 goto end; 4113 } 4114 4115 SDPDBG("Total svc count: %d\n", tsrc); 4116 SDPDBG("Current svc count: %d\n", csrc); 4117 4118 /* parameter length without continuation state */ 4119 plen = sizeof(tsrc) + sizeof(csrc) + csrc * 4; 4120 4121 if (t->rsp_concat_buf.data_size == 0) { 4122 /* first fragment */ 4123 rsp_count = sizeof(tsrc) + sizeof(csrc) + csrc * 4; 4124 } else { 4125 /* point to the first csrc */ 4126 uint16_t *pcsrc = (uint16_t *) (t->rsp_concat_buf.data + 2); 4127 4128 /* FIXME: update the interface later. csrc doesn't need be passed to clients */ 4129 4130 pdata += sizeof(uint16_t); /* point to csrc */ 4131 4132 /* the first csrc contains the sum of partial csrc responses */ 4133 *pcsrc += bt_get_unaligned((uint16_t *) pdata); 4134 4135 pdata += sizeof(uint16_t); /* point to the first handle */ 4136 rsp_count = csrc * 4; 4137 } 4138 status = 0x0000; 4139 break; 4140 case SDP_SVC_ATTR_RSP: 4141 case SDP_SVC_SEARCH_ATTR_RSP: 4142 rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); 4143 SDPDBG("Attrlist byte count : %d\n", rsp_count); 4144 4145 /* 4146 * Number of bytes in the AttributeLists parameter(without 4147 * continuation state) + AttributeListsByteCount field size. 4148 */ 4149 plen = sizeof(uint16_t) + rsp_count; 4150 4151 pdata += sizeof(uint16_t); // points to attribute list 4152 status = 0x0000; 4153 break; 4154 case SDP_ERROR_RSP: 4155 status = ntohs(bt_get_unaligned((uint16_t *) pdata)); 4156 size = ntohs(rsphdr->plen); 4157 4158 /* error code + error info */ 4159 plen = size; 4160 goto end; 4161 default: 4162 t->err = EPROTO; 4163 SDPERR("Illegal PDU ID: 0x%x", rsphdr->pdu_id); 4164 goto end; 4165 } 4166 4167 pcstate = (sdp_cstate_t *) (pdata + rsp_count); 4168 4169 SDPDBG("Cstate length : %d\n", pcstate->length); 4170 4171 /* 4172 * Check out of bound. Continuation state must have at least 4173 * 1 byte: ZERO to indicate that it is not a partial response. 4174 */ 4175 if ((n - (int) sizeof(sdp_pdu_hdr_t)) != (plen + pcstate->length + 1)) { 4176 t->err = EPROTO; 4177 SDPERR("Protocol error: wrong PDU size."); 4178 status = 0xffff; 4179 goto end; 4180 } 4181 4182 /* 4183 * This is a split response, need to concatenate intermediate 4184 * responses and the last one which will have cstate length == 0 4185 */ 4186 t->rsp_concat_buf.data = realloc(t->rsp_concat_buf.data, t->rsp_concat_buf.data_size + rsp_count); 4187 targetPtr = t->rsp_concat_buf.data + t->rsp_concat_buf.data_size; 4188 t->rsp_concat_buf.buf_size = t->rsp_concat_buf.data_size + rsp_count; 4189 memcpy(targetPtr, pdata, rsp_count); 4190 t->rsp_concat_buf.data_size += rsp_count; 4191 4192 if (pcstate->length > 0) { 4193 int reqsize, cstate_len; 4194 4195 reqhdr->tid = htons(sdp_gen_tid(session)); 4196 4197 // add continuation state 4198 cstate_len = copy_cstate(t->reqbuf + t->reqsize, 4199 SDP_REQ_BUFFER_SIZE - t->reqsize, pcstate); 4200 4201 reqsize = t->reqsize + cstate_len; 4202 4203 // set the request header's param length 4204 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 4205 4206 if (sdp_send_req(session, t->reqbuf, reqsize) < 0) { 4207 SDPERR("Error sendind data:%s(%d)", strerror(errno), errno); 4208 status = 0xffff; 4209 t->err = errno; 4210 goto end; 4211 } 4212 err = 0; 4213 } 4214 4215end: 4216 if (err) { 4217 if (t->rsp_concat_buf.data_size != 0) { 4218 pdata = t->rsp_concat_buf.data; 4219 size = t->rsp_concat_buf.data_size; 4220 } 4221 if (t->cb) 4222 t->cb(pdu_id, status, pdata, size, t->udata); 4223 } 4224 4225 if (rspbuf) 4226 free(rspbuf); 4227 4228 return err; 4229} 4230 4231/* 4232 * This is a service search request combined with the service 4233 * attribute request. First a service class match is done and 4234 * for matching service, requested attributes are extracted 4235 * 4236 * INPUT : 4237 * 4238 * sdp_list_t *search 4239 * Singly linked list containing elements of the search 4240 * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16) 4241 * of the service to be searched 4242 * 4243 * AttributeSpecification attrSpec 4244 * Attribute identifiers are 16 bit unsigned integers specified 4245 * in one of 2 ways described below : 4246 * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers 4247 * They are the actual attribute identifiers in ascending order 4248 * 4249 * SDP_ATTR_REQ_RANGE - 32bit identifier range 4250 * The high-order 16bits is the start of range 4251 * the low-order 16bits are the end of range 4252 * 0x0000 to 0xFFFF gets all attributes 4253 * 4254 * sdp_list_t *attrids 4255 * Singly linked list containing attribute identifiers desired. 4256 * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL) 4257 * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE) 4258 * 4259 * OUTPUT : 4260 * int return value 4261 * 0: 4262 * The request completed successfully. This does not 4263 * mean the requested services were found 4264 * -1: 4265 * On any error and sets errno 4266 * 4267 * sdp_list_t **rsp 4268 * This variable is set on a successful return to point to 4269 * service(s) found. Each element of this list is of type 4270 * sdp_record_t* (of the services which matched the search list) 4271 */ 4272int 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) 4273{ 4274 int status = 0; 4275 uint32_t reqsize = 0, _reqsize; 4276 uint32_t rspsize = 0; 4277 int seqlen = 0, attr_list_len = 0; 4278 int rsp_count = 0, cstate_len = 0; 4279 unsigned int pdata_len; 4280 uint8_t *pdata, *_pdata; 4281 uint8_t *reqbuf, *rspbuf; 4282 sdp_pdu_hdr_t *reqhdr, *rsphdr; 4283 uint8_t dataType; 4284 sdp_list_t *rec_list = NULL; 4285 sdp_buf_t rsp_concat_buf; 4286 sdp_cstate_t *cstate = NULL; 4287 4288 if (reqtype != SDP_ATTR_REQ_INDIVIDUAL && reqtype != SDP_ATTR_REQ_RANGE) { 4289 errno = EINVAL; 4290 return -1; 4291 } 4292 4293 memset(&rsp_concat_buf, 0, sizeof(sdp_buf_t)); 4294 4295 reqbuf = malloc(SDP_REQ_BUFFER_SIZE); 4296 rspbuf = malloc(SDP_RSP_BUFFER_SIZE); 4297 if (!reqbuf || !rspbuf) { 4298 errno = ENOMEM; 4299 status = -1; 4300 goto end; 4301 } 4302 4303 reqhdr = (sdp_pdu_hdr_t *) reqbuf; 4304 reqhdr->pdu_id = SDP_SVC_SEARCH_ATTR_REQ; 4305 4306 // generate PDU 4307 pdata = reqbuf + sizeof(sdp_pdu_hdr_t); 4308 reqsize = sizeof(sdp_pdu_hdr_t); 4309 4310 // add service class IDs for search 4311 seqlen = gen_searchseq_pdu(pdata, search); 4312 4313 SDPDBG("Data seq added : %d\n", seqlen); 4314 4315 /* now set the length and increment the pointer */ 4316 reqsize += seqlen; 4317 pdata += seqlen; 4318 4319 bt_put_unaligned(htons(SDP_MAX_ATTR_LEN), (uint16_t *) pdata); 4320 reqsize += sizeof(uint16_t); 4321 pdata += sizeof(uint16_t); 4322 4323 SDPDBG("Max attr byte count : %d\n", SDP_MAX_ATTR_LEN); 4324 4325 /* get attr seq PDU form */ 4326 seqlen = gen_attridseq_pdu(pdata, attrids, 4327 reqtype == SDP_ATTR_REQ_INDIVIDUAL ? SDP_UINT16 : SDP_UINT32); 4328 if (seqlen == -1) { 4329 status = EINVAL; 4330 goto end; 4331 } 4332 pdata += seqlen; 4333 SDPDBG("Attr list length : %d\n", seqlen); 4334 reqsize += seqlen; 4335 *rsp = 0; 4336 4337 /* save before Continuation State */ 4338 _pdata = pdata; 4339 _reqsize = reqsize; 4340 4341 do { 4342 reqhdr->tid = htons(sdp_gen_tid(session)); 4343 4344 /* add continuation state (can be null) */ 4345 reqsize = _reqsize + copy_cstate(_pdata, 4346 SDP_REQ_BUFFER_SIZE - _reqsize, cstate); 4347 4348 /* set the request header's param length */ 4349 reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t)); 4350 rsphdr = (sdp_pdu_hdr_t *) rspbuf; 4351 status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize); 4352 if (rspsize < sizeof(sdp_pdu_hdr_t)) { 4353 SDPERR("Unexpected end of packet"); 4354 status = -1; 4355 goto end; 4356 } 4357 4358 if (status < 0) { 4359 SDPDBG("Status : 0x%x\n", rsphdr->pdu_id); 4360 goto end; 4361 } 4362 4363 if (rsphdr->pdu_id == SDP_ERROR_RSP) { 4364 status = -1; 4365 goto end; 4366 } 4367 4368 pdata = rspbuf + sizeof(sdp_pdu_hdr_t); 4369 pdata_len = rspsize - sizeof(sdp_pdu_hdr_t); 4370 4371 if (pdata_len < sizeof(uint16_t)) { 4372 SDPERR("Unexpected end of packet"); 4373 status = -1; 4374 goto end; 4375 } 4376 4377 rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata)); 4378 attr_list_len += rsp_count; 4379 pdata += sizeof(uint16_t); // pdata points to attribute list 4380 pdata_len -= sizeof(uint16_t); 4381 4382 if (pdata_len < rsp_count + sizeof(uint8_t)) { 4383 SDPERR("Unexpected end of packet: continuation state data missing"); 4384 status = -1; 4385 goto end; 4386 } 4387 4388 cstate_len = *(uint8_t *) (pdata + rsp_count); 4389 4390 SDPDBG("Attrlist byte count : %d\n", attr_list_len); 4391 SDPDBG("Response byte count : %d\n", rsp_count); 4392 SDPDBG("Cstate length : %d\n", cstate_len); 4393 /* 4394 * This is a split response, need to concatenate intermediate 4395 * responses and the last one which will have cstate_len == 0 4396 */ 4397 if (cstate_len > 0 || rsp_concat_buf.data_size != 0) { 4398 uint8_t *targetPtr = NULL; 4399 4400 cstate = cstate_len > 0 ? (sdp_cstate_t *) (pdata + rsp_count) : 0; 4401 4402 /* build concatenated response buffer */ 4403 rsp_concat_buf.data = realloc(rsp_concat_buf.data, rsp_concat_buf.data_size + rsp_count); 4404 targetPtr = rsp_concat_buf.data + rsp_concat_buf.data_size; 4405 rsp_concat_buf.buf_size = rsp_concat_buf.data_size + rsp_count; 4406 memcpy(targetPtr, pdata, rsp_count); 4407 rsp_concat_buf.data_size += rsp_count; 4408 } 4409 } while (cstate); 4410 4411 if (attr_list_len > 0) { 4412 int scanned = 0; 4413 4414 if (rsp_concat_buf.data_size != 0) { 4415 pdata = rsp_concat_buf.data; 4416 pdata_len = rsp_concat_buf.data_size; 4417 } 4418 4419 /* 4420 * Response is a sequence of sequence(s) for one or 4421 * more data element sequence(s) representing services 4422 * for which attributes are returned 4423 */ 4424 scanned = sdp_extract_seqtype(pdata, pdata_len, &dataType, &seqlen); 4425 4426 SDPDBG("Bytes scanned : %d\n", scanned); 4427 SDPDBG("Seq length : %d\n", seqlen); 4428 4429 if (scanned && seqlen) { 4430 pdata += scanned; 4431 pdata_len -= scanned; 4432 do { 4433 int recsize = 0; 4434 sdp_record_t *rec = sdp_extract_pdu(pdata, pdata_len, &recsize); 4435 if (rec == NULL) { 4436 SDPERR("SVC REC is null\n"); 4437 status = -1; 4438 goto end; 4439 } 4440 if (!recsize) { 4441 sdp_record_free(rec); 4442 break; 4443 } 4444 scanned += recsize; 4445 pdata += recsize; 4446 pdata_len -= recsize; 4447 4448 SDPDBG("Loc seq length : %d\n", recsize); 4449 SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle); 4450 SDPDBG("Bytes scanned : %d\n", scanned); 4451 SDPDBG("Attrlist byte count : %d\n", attr_list_len); 4452 rec_list = sdp_list_append(rec_list, rec); 4453 } while (scanned < attr_list_len && pdata_len > 0); 4454 4455 SDPDBG("Successful scan of service attr lists\n"); 4456 *rsp = rec_list; 4457 } 4458 } 4459end: 4460 if (rsp_concat_buf.data) 4461 free(rsp_concat_buf.data); 4462 if (reqbuf) 4463 free(reqbuf); 4464 if (rspbuf) 4465 free(rspbuf); 4466 return status; 4467} 4468 4469/* 4470 * Find devices in the piconet. 4471 */ 4472int sdp_general_inquiry(inquiry_info *ii, int num_dev, int duration, uint8_t *found) 4473{ 4474 int n = hci_inquiry(-1, 10, num_dev, NULL, &ii, 0); 4475 if (n < 0) { 4476 SDPERR("Inquiry failed:%s", strerror(errno)); 4477 return -1; 4478 } 4479 *found = n; 4480 return 0; 4481} 4482 4483int sdp_close(sdp_session_t *session) 4484{ 4485 struct sdp_transaction *t; 4486 int ret; 4487 4488 if (!session) 4489 return -1; 4490 4491 ret = close(session->sock); 4492 4493 t = session->priv; 4494 4495 if (t) { 4496 if (t->reqbuf) 4497 free(t->reqbuf); 4498 4499 if (t->rsp_concat_buf.data) 4500 free(t->rsp_concat_buf.data); 4501 4502 free(t); 4503 } 4504 free(session); 4505 return ret; 4506} 4507 4508static inline int sdp_is_local(const bdaddr_t *device) 4509{ 4510 return memcmp(device, BDADDR_LOCAL, sizeof(bdaddr_t)) == 0; 4511} 4512 4513static int sdp_connect_local(sdp_session_t *session) 4514{ 4515 struct sockaddr_un sa; 4516 4517 session->sock = socket(PF_UNIX, SOCK_STREAM, 0); 4518 if (session->sock < 0) 4519 return -1; 4520 session->local = 1; 4521 4522 sa.sun_family = AF_UNIX; 4523 strcpy(sa.sun_path, SDP_UNIX_PATH); 4524 4525 return connect(session->sock, (struct sockaddr *)&sa, sizeof(sa)); 4526} 4527 4528static int sdp_connect_l2cap(const bdaddr_t *src, 4529 const bdaddr_t *dst, sdp_session_t *session) 4530{ 4531 uint32_t flags = session->flags; 4532 struct sockaddr_l2 sa; 4533 int sk; 4534 4535 session->sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 4536 if (session->sock < 0) 4537 return -1; 4538 session->local = 0; 4539 4540 sk = session->sock; 4541 4542 if (flags & SDP_NON_BLOCKING) { 4543 long arg = fcntl(sk, F_GETFL, 0); 4544 fcntl(sk, F_SETFL, arg | O_NONBLOCK); 4545 } 4546 4547 memset(&sa, 0, sizeof(sa)); 4548 4549 sa.l2_family = AF_BLUETOOTH; 4550 sa.l2_psm = 0; 4551 4552 if (bacmp(src, BDADDR_ANY)) { 4553 sa.l2_bdaddr = *src; 4554 if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) 4555 return -1; 4556 } 4557 4558 if (flags & SDP_WAIT_ON_CLOSE) { 4559 struct linger l = { .l_onoff = 1, .l_linger = 1 }; 4560 setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); 4561 } 4562 4563 sa.l2_psm = htobs(SDP_PSM); 4564 sa.l2_bdaddr = *dst; 4565 4566 do { 4567 int ret = connect(sk, (struct sockaddr *) &sa, sizeof(sa)); 4568 if (!ret) 4569 return 0; 4570 if (ret < 0 && (flags & SDP_NON_BLOCKING) && 4571 (errno == EAGAIN || errno == EINPROGRESS)) 4572 return 0; 4573 } while (errno == EBUSY && (flags & SDP_RETRY_IF_BUSY)); 4574 4575 return -1; 4576} 4577 4578sdp_session_t *sdp_connect(const bdaddr_t *src, 4579 const bdaddr_t *dst, uint32_t flags) 4580{ 4581 sdp_session_t *session; 4582 int err; 4583 4584 if ((flags & SDP_RETRY_IF_BUSY) && (flags & SDP_NON_BLOCKING)) { 4585 errno = EINVAL; 4586 return NULL; 4587 } 4588 4589 session = sdp_create(-1, flags); 4590 if (!session) 4591 return NULL; 4592 4593 if (sdp_is_local(dst)) { 4594 if (sdp_connect_local(session) < 0) 4595 goto fail; 4596 } else { 4597 if (sdp_connect_l2cap(src, dst, session) < 0) 4598 goto fail; 4599 } 4600 4601 return session; 4602 4603fail: 4604 err = errno; 4605 if (session->sock >= 0) 4606 close(session->sock); 4607 if (session->priv) 4608 free(session->priv); 4609 free(session); 4610 errno = err; 4611 4612 return NULL; 4613} 4614 4615int sdp_get_socket(const sdp_session_t *session) 4616{ 4617 return session->sock; 4618} 4619 4620uint16_t sdp_gen_tid(sdp_session_t *session) 4621{ 4622 return session->tid++; 4623} 4624