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