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